かみのメモ

プログラムな話題中心の勉強メモ

東工大 情報理工学院のA日程を外部受験した話

2019年入学の東工大 情報理工学院 情報工学系を受験したのでそのメモ。 誰かの参考になればということで残しておきます。

まず参考までに自分のスペックを。

  • 某旧帝出身
  • B4時に内部の院試を受けて爆死->院浪
  • GPA2.5とか
  • TOEIC700いかないくらい

4月

卒研関連の諸々が終わり、院浪生活開始。 とはいえ学部の研究室に引き続き通わせてもらっていたので、それまでとあまり環境は変わらず。

せっかく浪人するなら専攻変える選択肢もあるよなーと思い、周りの人に相談しつつ志望研究室の情報収集をする。 その中で以前から知っていた東工大の先生の研究室が候補に上がる。

5月中旬

学部の研究室の先生に顔つなぎをしてもらい、入試説明会の日程に合わせて研究室見学に行く。

東工大は4月から5月にかけて何度か入試説明会を開いているが、会場になるキャンパスにある研究室しか見学に行けない上、日によっては研究室を公開していないところもあるので注意が必要。 実際、私が行った研究室も当日配られた公開研究室のリストには載っていなかった。 事前にメールしておくのが吉。

2時間くらいお話を聞かせてもらい、晩ご飯までご馳走になってしまった()

他の大学院見学もこの時期に行った。 またこの頃から数学の勉強を始めた。

6月中旬

出願。

併願していた大学の小論文に手こずったこともあり、東工大の出願書類はかなりギリギリの日程で仕上げた。 消印有効ではなく必着だったし、提出直前に大阪府北部地震が来て交通網が荒れてたので結構冷汗かいた。 とりあえず無事に届いたらしい。

志望動機書は指定文字数が少なかったので、素直に書いたら割とぴったり埋まった。 住所記入欄多すぎ。

6月下旬

先輩の伝手で東工大情報理工に在学中の方に「使ってた教科書とか教えてください」と聞いてもらったところ、「過去問で勉強したら十分だと思うよ」という返事をいただく。

情報工学系は2016年から出題傾向がガラッと変わったのでどう勉強しようか困った。 とりあえず論理回路情報理論オートマトン形式言語etc)は内部の院試では出題されなかった範囲なので、その辺りから勉強し始めた。

7月中旬

受験票が届く。

A日程受験資格が降ってきたのでめちゃくちゃ驚いた。 内部生もしくは外部生の超成績優秀者しか受けられないと思っていた。

慌ててA日程の情報収集をしたところ、

  • 成績上位者から順に面接に呼ばれる
  • 各研究室にA日程合格枠の上限があり、結局は同じ研究室を志望する他の受験者との枠の取り合いになる

らしいと知る。

7月下旬

A日程受験。

関西在住なので前日に東京入りした。

会場に入るとき、研究室見学のときに会った志望研究室のB4の人を見かけてちょっと絶望する(枠を取られるだろうなと思った)。 受験番号的に総受験者数は200人、A日程受験者は80人くらいだと思う(±20%)。 やはり大半が内部生という雰囲気だった。

面接は5~6部屋くらい並列でやっているよう(最初にまとめて呼ばれた人数がそれくらいだった)で、2~5分に1人のペースで呼ばれていった。 私が呼ばれたのは半分超えたか、というところ。

面接室では先生が5人、志望研究室の先生を含め、分野の近しい先生方が集まっている様子だった。 面接は合計30分くらい。 真ん中に座っている先生がタイムスケジュール表を見て進行役をやっていた。

以下うろ覚えだけど面接の内容。 外部生と内部生で内容違う可能性あり。

  1. 志望研究室の確認
    • 第一志望と第二志望を再確認された(おそらくA日程で合格可能性があるのが第二志望までなんでしょう)
  2. 卒研について
    • 「5分で内容を説明してください。ホワイトボードを使ってもかまいません」
    • 紹介した内容についての質問(「評価方法どうしたの?」とか「こういう問題出そうだけどどう解決したの?」とか)
  3. 情報工学の知識の確認
    • 基本質問
      • JPEGの圧縮方式を説明してください」
    • 専門分野関連の質問
      • 「卒研でCG使ってるんですよね?じゃあ3DデータをPC上でどう保持しているか説明してください」
      • 「卒研で使ってたこの機材には2つの方式がありますが、それを説明してください」etc
  4. その他
    • 志望理由
    • 学部時代の印象に残った授業
    • 課外活動などなんでもいいのでこれまでに成果を挙げたもの
    • どうして去年落ちたの?
  5. 意思確認
    • もし第一志望落ちたらB日程受験を希望するか、第二志望への合格を希望するか

研究分野についてはかなり勉強していたので答えに困った場面はほとんどなかった。 JPEGのとこで知らない知識問題が来てたらやばかった。

8月上旬

B日程の勉強をせねばと思いつつも、結果発表まで全く身が入らなかった。

発送予定日の午後に速達で出すとして、次の日くらいには届くだろうと予想していた。 実際には普通郵便で送られてきたので、さらに丸一日待たされた。

封筒を開くと第一志望研究室に内定したとの通知が入っていて無事院試終了。


出願書類上の成績はそんなによくなかったのにA日程受験資格者に選ばれたのが最大の謎。

それでも第一志望の研究室に入れたということは、内部生・外部生関係なく面接の内容がちゃんと評価されてるのだと思った。

何はともあれ来年はニート脱却。

OpenCV入門するならまずサンプルコードを動かしてみよう

以前のWindowsでOpenCV+contribをビルド・インストールするに引き続きOpenCVネタ。

OpenCVリポジトリに用意されているサンプルコードがなかなかバリエーション豊かで勉強になることに気付いたので、宣伝したいと思います。

OpenCVのサンプル集

https://github.com/opencv/opencv/tree/master/samplesを見てのとおりC++JavaPython向けのものからandroid、DNN、OpenGLなど特定の環境と組み合わせる用のものまで様々なサンプルが用意されています。

この記事では環境構築とサンプルコードの実行が簡単なPython向けサンプルをとりあえず試してみます。

インストールしておくもの

  • Python
    • 一応Python 2でも動くらしいですが、Python3を使うのが無難だと思います
    • 筆者の環境は3.7.0
  • Git

OpenCVライブラリのインストール

Pythonのパッケージマネージャーpipを使います。 いくつかのサンプルはOpenCVの外部モジュールであるopencv-contribを利用するのでそちらも一緒にインストールしておきます。

python -m pip install opencv-python opencv-contrib-python

サンプルのダウンロード

サンプルコードとかサンプル画像を取得するためにOpenCVリポジトリを丸ごとクローンします。 適当なディレクトリを作って次のコマンドを実行します。

git clone https://github.com/opencv/opencv.git

サンプルを実行してみる

サンプルのダウンロードが終わったらopencv/samples/pythonの中に大量のpythonファイルが入っていると思います。 その中の1つdemo.pyを実行します。

cd opencv/samples/python
python demo.py

すると次のような画面が出てきて、サンプルコードの一覧を確認することができます。

f:id:kamino-dev:20180904180746p:plain

とりあえずbrowseを選択してRunボタンを押してみます。 するとサンプルbrowse.pyが起動します。

f:id:kamino-dev:20180904181700p:plain

マウスカーソルを当てた場所が拡大して表示される、というだけの簡単なプログラムですが、きちんと動いていることがわかります。 プログラムを終了するときはESCキーを押します。

もしWindowsユーザーで'C:\Program' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。のようなエラーが出たら一旦画面を閉じて、demo.pyの170行目あたりのPopen(sys.executable + ' ' + cmd, shell=True)Popen('"' + sys.executable + '" ' + cmd, shell=True)に変更してもう一度実行してみてください。

ついでにもう一つdeconvolutionを実行してみます。

f:id:kamino-dev:20180904182628p:plain

今度はもう少し実践的なデモです。 左のような手ブレ写真にdeconvolution(畳み込み演算の逆の処理)を施すことで手ブレによるノイズを除去し、右のような画像への復元をしています。 右上のスライダーを動かしてカーネルのパラメータを調節できるようになっています。


この他にもカメラキャリブレーションcalibrate)、Canny法によるエッジ検出(edge)、顔認識(facedetect)、Webカメラで物体追跡(camshift)など色々なサンプルがあるので、自分でプログラムを書くときの参考にしてみてください。

(時間ができたら全サンプルの解説記事とか書いてみたいなぁ)

AngularでHttpClientのgetのためにbase-hrefを取得する

どういう状況?

Angular 6.1.3でアプリを作っているときのこと。

「最終的にxxxx.example.comにデプロイするけど、とりあえずデモのためにxxxx.github.io/xxxx.example.comで公開したいな」と思いたちました。

そこでangular-cli-ghpagesを使って、

ng build --prod --base-href "https://xxxx.github.io/xxxx.example.com"
angular-cli-ghpages --repo=https://github.com/~~~~~~~

みたいな感じで公開しようとしました。

ところが、

//省略

export DataService {
  constructor(private http: HttpClient) { }

  getTopics() {
    return this.http.get('/data/topics.json');
  }
}

のように、静的なJSONファイルを取得しようとしたときhttps://xxxx.github.io/data/topics.jsonにアクセスしてしまい404が返ってきてしまいました。 実際にファイルが置かれているのはhttps://xxxx.github.io/xxxx.example.com/data/topics.jsonです。

どうやらHttpClientget()はホスト名を参照するのであって、base-hrefを参照してくれるわけではないようです。

解決方法

調べてみるとコードにbaseUrl: String = 'xxxx.github.io/xxxx.example.com';を埋め込む方法がよく紹介されていましたが、今回は最終的にxxxx.example.comにデプロイしたいので固定値を埋め込むのは遠慮したいところです。

かと言って、DOMを介して取得する、みたいな泥臭い方法は取りたくないです。

という感じで調べていくとこんな記述を見つけました。 どうやらLocationprepareExternalUrlが使えるらしい。

ということでコードを修正。

import { Location } from '@angular/common';

//省略

export DataService {
  constructor(private http: HttpClient, private location: Location) { }

  getTopics() {
    return this.http.get(this.location.prepareExternalUrl('/data/topics.json'));
  }
}

これで動きました!

RustからCUDAのカーネルを呼んでみた【Windows】

RustとCUDAを連携させて遊んでみた。

参考にしたのはこちらのサイト↓ qiita.com

ほとんどこの記事の通りに書けばよいのですが、私の環境はWindowsで、build.rsの辺りで若干苦戦したのでその辺りについてまとめてみます。

環境

普通にVS Community 2017、CUDA Toolkit、Rustをインストールした環境です。 RustはNightlyを使っていますが、Stableでも動くはずです。

Windows 10 Pro
Visual Studio 2017

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Wed_Apr_11_23:16:30_Central_Daylight_Time_2018
Cuda compilation tools, release 9.2, V9.2.88

rustc 1.28.0-nightly (e3bf634e0 2018-06-28)

build.rs

今回書いたbuild.rsです。

use std::env;
use std::process::Command;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    Command::new("nvcc")
        .args(&["src/vectorAdd.cu",
            // static library (.lib) を出力させる
            "-lib",
            // Cコンパイラのパスを指定
            "-ccbin", 
            r"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\Hostx64\x64\cl.exe",
            // Cコンパイラにwarning 4819を無視するよう指示
            "-Xcompiler", "-wd4819",
            "-o"])
        .arg(&format!("{}/kernel.lib", out_dir))
        .status()
        .unwrap();

    println!("cargo:rustc-link-search=native=C:/PROGRA~1/NVIDIA~2/CUDA/v9.2/lib/x64");
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=cudart");
    println!("cargo:rustc-link-lib=kernel");
}

まず、nvccvectorAdd.cuをビルドする部分について解説します。

Visual Cのコンパイラcl.exeはPATHに追加されていないので、nvccに場所を教えてやる必要があります。 ついでに、CUDAのヘッダファイルの文字コードのせいでC4819の警告が大量に出てくるので、これを無視するように指定しておきます。 Rustのビルドに混ぜ込むためにはオブジェクトファイルではなく静的ライブラリファイルが必要らしいので、-libオプションを付け、kernel.libを吐き出すように指定しておきます。

次に、rustcのオプションを指定する部分について。

やっていることは、単にライブラリのサーチパスを追加しているだけです。 ただしWindowsの場合、パスにスペースを含むケースがあります。 スペースを含んだままrustcに渡すとオプションが正しく認識されないのでビルドに失敗してしまいます。 また、いまのところcargo:rustc-link-search=native='path~~'のようにクォーテーションで囲っても正しく認識してくれないようです。 ということで、PROGRA~1のような短縮記法を使ってパスを指定します(短縮したパス名の調べ方はこちらのページなどを参考に)。

ちなみにライブラリのサーチパスの追加等はcargoのconfigファイルからでも行えるようです(ドキュメント)。

自分の環境ではこれで動きました。

雑感

この他にも、nvptxとかaccelとかのcrateを使う方法もあるようですね。

以前試してみたのですが、Windowsarコマンドがなかったり、なぜか実行時にエラーが出たりとハマりどころが多かったので、今回は単純にcuファイルをビルドして混ぜ込む方法でやってみました。

しかし、Windowsのパス周りは本当になんとかしてほしい。。。

CUDA9.2でunsupported Microsoft Visual Studio version!とか言われた

Visual Studio 2017でCUDA SDK v9.2のテンプレートプロジェクトをビルドしようとしたら以下のようなエラーが出た。

unsupported Microsoft Visual Studio version! Only the versions 2012, 2013, 2015 and 2017 are supported!

…いやいや、VS2017使ってるんですけど。。

調べてみると、どうもVSの更新にCUDAがついてこれていないみたい。

とりあえず応急措置として、path_to_cuda/include/crt/host_config.hの170行目あたりを書き換える。

#if _MSC_VER < 1600 || _MSC_VER > 1910

#error-- unsupported Microsoft Visual Studio version! Only the versions 2012, 2013, 2015 and 2017 are supported!

_MSC_VERのバージョン番号が1910以上になってるのが原因っぽいので、この値を適当に1920とかにしておく。

リビルドしてみるととりあえず動いた。

Rustのimageのピクセル処理をRayonで並列化する

これ↓を書くときに困ったのでメモ。

github.com

Rustのimageピクセルごとの処理を書くときはenumerate_pixels_mut()を使うらしい。

これにRayonpar_iter_mut()を組み合わせて、処理を並列化してみる。

extern crate image;
extern crate rayon;

use image::{Rgb, RgbImage};
use rayon::prelude::*;

fn gen_img() -> RgbImage {
    let mut img = RgbImage::new(1200, 800);
    img.enumerate_pixels_mut()
        .collect::<Vec<(u32, u32, &mut Rgb<u8>)>>()
        .par_iter_mut()
        .for_each(|(x, y, pixel)| {
            pixel[0] = (255.0 * (*x as f64 / 1200.0)) as u8;
            pixel[1] = (255.0 * (*y as f64 / 1200.0)) as u8;
            pixel[2] = 128;
        });
    img
}

fn main() {
    let img = gen_img();
    img.save("sample.png").unwrap();
}

これで並列化できてるはず。 一応ベンチマークを取ってみる。

iter_mut()のとき

bench:  22,650,690 ns/iter (+/- 2,139,697)

par_iter_mut()のとき

bench:  16,251,080 ns/iter (+/- 1,763,219)

やはりこの程度の軽い処理ではあまり差が出ないようだが、ちゃんと並列演算してくれてるっぽい。


まだIteratorの扱い方を完全に把握できていないので勉強したい。

ipythonで「Fatal error in launcher」が出た話

Windows 10 Home
Python 3.6.5
IPython 6.3.1

Windows 10上のPythonを3.6.5にアップグレードしたところ、ipyhonがコケるようになった。

f:id:kamino-dev:20180517132459p:plain

なんでやねん。

Pathを確認してもpython.exeが重複しているとかいうことはなかった。

そこでもう一度エラーメッセージを読んでみる。

Fatal error in launcher: Unable to create process using '""c:\program files\python36\python.exe"  "C:\Program Files\Python36\Scripts\ipython.exe" '

あれ、"の数おかしくね?

ということでコマンドを修正して実行してみる。

python "C:\Program Files\Python36\Scripts\ipython.exe"

f:id:kamino-dev:20180517133938p:plain

動いた。


とりあえずipythonは使えるようになったものの、理由がいまいちはっきりしない。

ipython.exeを実行するときに別のpython.exeを使おうとしてるのだろうか?