for vs range based for vs for_each

c++でループを回す方法として、for, range based for, for_each がある。

どれが速いのか気になったので測ってみた。

 

要素が100000個あるvectorの全ての要素を2倍するというタスクで比較してみた。

① for

std::vector<int> vec1(100000, 1);
for (int i = 0; i < vec1.size(); ++i) {
    vec1[i] *= 2;
}

② rage based for

range based for は c++11で追加された機能。

詳しくは: 

範囲for文 - cpprefjp C++日本語リファレンス

std::vector<int> vec2(100000, 1);
for (int& v : vec2) {
    v *= 2;
}

③ for_each

あまり知られていない機能ですが、いわゆるmapをする関数です。algorithmヘッダーにあります。

詳しくは:

for_each - cpprefjp C++日本語リファレンス

std::vector<int> vec3(100000, 1);
std::for_each(vec3.begin(), vec3.end(), [](int& x) {x *= 2;});

結果

time[msec]
①for 2.2172
②range-based for 4.9361
③for_each 4.7552

forを使ったほうが2倍以上速いという結果になった。

C++ 配列コピーの速度

パディング処理をして新しい配列を作るときに、どのようにしてコピーするのが速いのか気になったので、比較してみた。

下図のような処理を、①逐次コピー ②std::copy ③memmove ④memcpyで実装して速度を比較してみた。 f:id:wakanapo:20180522162743p:plain

元の配列の大きさをcol × row、パディングをpadとした。

①逐次コピー

std::array<int, (row+2*pad)*(col+2*pad)> arr1 = {};
for (int i = 0; i < col; ++i) {
  for (int j = 0; j < row; ++j) {
      arr1[(i+pad)*(row+2*pad) + (j+pad)] = arr[i*row + j];
  }
}

②std::copy

std::array<int, (row+2*pad)*(col+2*pad)> arr2 = {};
for (int i = 0; i < col; ++i) {
  std::copy(arr.begin() + i*row, arr.begin() + (i+1)*row, 
            arr2.begin() + (i+pad)*(row+2*pad) + pad);
}

③memmove

std::array<int, (row+2*pad)*(col+2*pad)> arr3 = {};
for (int i = 0; i < col; ++i) {
  std::memmove(&(arr3[(i+pad)*(row+2*pad) + pad]), &(arr[i*row]), row*sizeof(int));
}

④memcpy

std::array<int, (row+2*pad)*(col+2*pad)> arr4 = {};
for (int i = 0; i < col; ++i) {
  std::memcpy(&(arr4[(i+pad)*(row+2*pad) + pad]), &(arr[i*row]), row*sizeof(int));
}

結果

col * row = 300 * 300, pad = 1として実験を行った。 chronoクラスのsteady_clockで実行時間を測定した。

それぞれ10回づつ実行した時の平均値はこのようになった。

time[μsec]
①逐次コピー 924.4
②std::copy 40.1
③memmove 21.9
④memcpy 19.9

memcpy vs memmove

memcpyはコピー元のbufferとコピー先にbufferが重なった時の動作が未定義という問題がある。 今回の処理では別のバッファに書き込んでいるので大丈夫だが、バッファが重なっていないことをcheckする処理を入れたほうが確実だろう。

ということで、バッファが重なっていないことをcheckする処理を入れてもmemcpyのほうが速いのか調べてみた。

if (!(arr4.begin() > arr.end() || arr.begin() > arr4.end()))
  abort();

arrayで確保される領域は連続しているので、これでcheckできているはずである。

col * row = 300 * 300, pad = 1として実験を行った。 chronoクラスのsteady_clockで実行時間を測定した。

それぞれ10回づつ実行した時の平均値はこのようになった。

time[μsec]
memmove 25.5
memcpy 25.0

300*300程度の配列では差はほとんどないことがわかった。

プログラムの進捗をTwitterで通知する

エポックごとに結果を出力するような時間のかかるプログラムをまわしていて、エポックごとの結果が出るたびになんらかの通知がくれば便利だなと思ったので作った。

作ったものの概要

結果が書き込まれるoutput.txtの行数を監視し、増えると最終行を読んでTwitterでReplyをとばすもの。 プログラムを回している間の暇な時間にぱぱっと作ったのでとても簡易的。

Replyをとばすプログラム

tweepyを使ってぱぱっと作りました。 twitterアカウントを複数持っていたので、アカウントの一つをbotとして他の自分のアカウントにReplyをとばすようにしました。

output.txtの行数を監視するプログラム

shellスクリプトでwcコマンドをぐるぐる回して監視しています。

最終的にはoutput.txtは30行になるはずなので、30行になったら監視を終了しています。

これで、observer.shと監視したいプログラムを実行すればokです。

CircleCI2.0+googletestでC++のテスト環境を構築

Docker Imageの作成

ubuntu:16.04のimageを元にしてclang+googletestの入ったImageを作成しました。

$ docker pull ubuntu:16.04
$ docker run --name my-ubuntu -it ubuntu:16.04 /bin/bash

clang+googletestの環境構築

# clangのinstall
$ apt update
$ apt install llvm build-essential clang

# googletestのinstall
$ apt install git cmake
$ git clone https://github.com/google/googletest.git
$ cd googletest
$ cmake -DBUILD_SHARED_LIBS=ON .
$ make
$ cp -a googletest/include/gtest /usr/include
$ cp -a googlemock/gtest/libgtest_main.so googlemock/gtest/libgtest.so /usr/lib/
$ exit
$ docker commit my-ubuntu wakanapo/clang-gtest
$ docker push wakanapo/clang-gtest

Makefileの用意

CXX := clang++
CXXFLAGS := -std=c++14 -Wall -O2 -lgtest_main -lgtest
SRCS := test.cc

test: $(SRCS) 
    $(CXX) $(CXXFLAGS) -o $@ $^

.PHONY: clean
clean:
    rm ./test

yamlファイルの用意

yamlファイルは.circleciというレポジトリの下に置きます。

version: 2
jobs:
  build:
    docker:
      - image: wakanapo/clang-gtest
    steps:
      - checkout
      - run:
          name: Make test
          command: make test
      - run:
          name: Running test
          command: ./test

平成29年度NW午前Iを解いた

Word

  • MTBF
    平均故障間隔(Mean Time Between Failure)のこと。
    稼働している時間を合計して故障回数で割ることで求められる。
    MTBFが大きいほど、故障までの時間や稼働している時間が長く信頼性が高いと言える。
    一回故障すると使えなくなるという場合(ハードディスク, SSDなど)はMTTF 平均故障時間が使われる。

  • MTTR
    平均修理時間(Mean Time To Repair)のこと。
    修理している時間を合計して故障回数で割ることで求められる。
    MTTRが小さいほど復旧や修理が早く保守性が高いといえる。

  • プリエンション
    マルチタスクのコンピュータ・システムが実行中のタスクを一時的に中断する動作であり、基本的にそのタスク自体の協力は不要で、後でそのタスクを再実行するという意味も含む。

  • CSMA/CD方式
    Carrier Sense Multiple Access with Collision Detectionの略
    1. イーサネット上のノードは自身が通信を開始する前に伝送路に他のノードが通信を行っていないか確認する。
    2. 伝送路に通信が流れていなければデータを送信する。
    3. もし他のノードの通信があった場合は通信が終わるのを待ってからランダムな待機時間後に送信を行う。
    4. イーサネットの伝送路につながっている全てのパソコンは、データが伝送路上に流れてくると自分宛のデータかどうかチェックして、自分宛のデータだけを取り込み、それ以外は捨てる。
    5. 複数のノードが同時に通信を行ってしまった場合には、コリジョンが発生しそのデータは破棄される。コリジョンが発生するとケーブル内の電圧が下がりケーブルに沿って電気信号が戻ってくる。これをジャム信号と呼ぶ。
    6. イーサネット上の各ノードがどのジャム信号を検知したらデータを送信するのをやめる。伝送路が開くのを待ってからランダムな待機時間後に再度送信する、再送の回数は最大で16回と決められており、16回で通信に成功しないと、通信失敗としてOS側へ通知される。

  • ドライブバイダウンロード攻撃
    Webにアクセスした際などに、その本人の知らないうちに何らかのソフトウェアを勝手にダウンロード、インストールする手口のこと。

  • サイバーレスキュー隊
    被害の低減:標的型攻撃メールが届いている組織や、検知した不審通信や 不正ログなどに対してその深刻度を認識できずにいる組織に 対して、標的型攻撃メールや組織のログ等の情報を分析する ことにより、感染経路の把握、感染の範囲などを分析し、必 要な対策の早期着手を支援します。発覚した攻撃のフェーズ に沿った支援活動のイメージを図 2.3 に示します。
    被害の拡大防止: 標的型サイバー攻撃の事案の対応の中で、標的型サイバー攻 撃による感染の連鎖(図 2.2 参照)を解明し、一連の攻撃の対 象となっていることを検知できずに「潜伏被害」を許してし まっていた場合に、その組織にコンタクトすることにより、 攻撃の連鎖の遮断を支援します

  • WAF
    Web Application Fireallの略。外部ネットワークからの不正アクセスを防ぐためのソフトウェアであるFireallの中でも、Webアプリケーションのやり取りを把握・管理することによって不正侵入を防御ですることのできるFireallのこと。

  • CMMI
    Capability Maturity Model Integration(能力成熟度モデル統合)の略。組織がプロセスをより適切に管理できるように成ることを目的として順守すべき指針を体系化したものである。

  • EVM
    Earned Value Managementの略。プロジェクトの計画予算と実際に発生した費用、およびそれまでに完了した作業量を対比することで、コストおよびスケジュール実績が計画とどの程度の乖離があるのかを明確化し、最終的な推定コスト・完了時期を予測する。

  • To-Beモデル
    企業などのあるべき姿や将来的な理想の姿を表す。

  • EA参照モデル
    政府が公開しているEAの雛形のこと

  • ザックマンモデル
    1987年ジョン・A・ザックマンによって提唱されたEAの基礎となっているフレームワークで、5種類の異なる立場の視点とそれぞれの5W1H(What、How、Where、Who、When、Why)の側面から分析・記述する手法。

  • データモデル
    対象業務を抽象的な形式で、情報システムやDBMSにおけるデータの表現方法としてモデル化したもの。

  • デルファイ法
    専門家グループなどが持つ直観的意見や経験的判断を反復型アンケートを使って、組織的に集約・洗練する意見収束技法。

Knowledge

  • JIS X 8341:2010(高齢者・障害者等配慮設計指針ー情報通信における機器、ソフトウェア及びサービスー第一部共通指針)
    多様な人々に対して、利用の状況を理解しながら、多くの個人のアクセシビリティ水準を改善できるようにすることを目的としている。

  • 重複データを除外して取得
    SELECT DISTINCT ~

  • 評価指標
    (最終成果物に含まれる誤りの件数)÷(最終成果物の量)=(信頼性の評価指標)
    (修正時間の合計)÷(修正件数)=(保守性の評価指標)
    (変更が必要となるソースコードの行数)÷(移植するソースコードの行数)=(移植性の評価指標)
    (利用者からの改良要求件数)÷(出荷後の経過月数)=(機能性の評価指標)

Link

http://www.pc-master.jp/words/mtbf-mttr.html

https://www.itbook.info/study/p26.html

https://japan.norton.com/drive-by-download-7958

https://www.ipa.go.jp/files/000047187.pdf

http://sm.seeeko.com/archives/65793782.html

http://www.ap-siken.com/kakomon/

http://www.itmedia.co.jp/im/articles/0805/26/news130.html



Deep Learning Day 2018に参加してきた

1月20日土曜日にDeep Learning Day 2018に参加してきました。

私が発表した内容については前の記事に書いたとおりです。

Deep Learning Day 2018とは

「先端人工知能II」という授業の最終成果発表会です。この講義は、公開講義になっていて社会人の人も「Deep Learning応用講座」という名前で受講することができます。ただし、対象は「先端人工知能論I(Deep Learning 基礎講座)」を受講済みの人なので注意してください。

一授業の最終成果発表会とはいえ、秋葉原UDXの会場を借りて、Deep MindやFacebook AIの人が基調講演に来てくださり、昼食・夕食も出る強いイベントです。"金"って感じでした。

発表

すごく面白いものを作っているチームがたくさんあったので私の印象に残ったものをいくつか紹介したいと思います。

①Deep Quoridor

このチームはコリドールというゲームのAIを作っていました。ボードゲーマ(ガチではない)の私は、もともとこのゲームをしっていたので中間発表で話を聞いた時から面白そう!と思っていました。ただ、コリドールのAIは調べると既に作っている人がいた(Quoridor AI)のでそのへんどうなのだろうと思っていました。

実際にDeep Quoridorのデモを試してみると、Deep Quoridorのほうが既存のものよりもレスポンスが早いと感じました。また、UIも綺麗だと思います。どちらのほうがAIとして賢いのかはわかりません・・・・。どちらのAIにも私は勝てないのでwww気が向いたら、この2つのAIを直接対決させてみたいと思います。

Deep Quoridor

②画風変換を駆使した顔はめパネル

漫画の主人公とかの美少女の顔はめパネルとかあると思いますが、せっかく顔はめして体と雰囲気は美少女になったのに、顔だけ元のままだと浮いちゃうし悲しい!みたいなのを改善してくれるものです(?)

顔の部分をパネルの画風に合わせて良い感じにしてくれます。

また、背景も絵風に変換してくれるので、実世界で顔はめしてとった写真から実際の漫画やアニメのワンシーンみたいな画像が生成できます。

③ANIBODY

人の動きに合わせてアバターをうごかせるようにしたものです。

発表の際レイテンシに気をつけたと強調していましたが、アイドルが複数人で踊っているような動画に対しても、ほぼレイテンシなく人数分のアバターを踊らせることができてました。

④俳句ジェネレーター

画像を与えると、それに合うような俳句を出力してくれるというものです。

正直言って、それほど精度はよくなかったです。575になっていない、季語が入っていない、日本語として意味がとれないというものも多々生成されてしまっていました。

ですが、私がためした卵かけご飯の写真ですごく良い感じなのが生成されて作成者の方もたまたまだと言っていて面白かったです。

f:id:wakanapo:20180125111106p:plain

haiku-generator.tokyo

⑤子供ジェネレータ

男女の顔写真を与えると、推定される子供の顔写真を生成してくれるものです。

テーマを聞いた時は、なんだよくあるやつか。と思っていたんですが、結構クオリティが高くて面白かったです。

会場にいた人はほぼ男性だったので、会場ではガッキーの写真と合成するデモをやっていました。

試してみますか?といわれて、思わず「えぇぇぇぇ、私とガッキーを合成するんですか・・・・?」となってしまいました。

だって、単純計算で2 * (子供の顔面偏差値) - (ガッキーの顔面偏差値) = (私の顔面偏差値)じゃないですか・・・(顔面偏差値は線形ではないのでは?とかそういう議論はいらない)。もし生成された子供が可愛くなかったら、完全に私のせいじゃないですか・・・。

冷静に考えると、別にそれは私が男であってもそういうことだし、それはそうって感じなんですが、別にガッキーとの合成じゃなくてもデモできるとのことだったので、デモしてくださってた方と私の子供の顔を生成しました(笑)

会場がちょっと暗めだったのか、生成された画像も暗っぽくなってしまいましたが、わかる〜って感じの画像生成されました。生成される子供の年齢をいじることもできます。

デモはJupyter Notebookでローカルで行っていたので、「こっそりいろんな人と試したいからぜひWebで公開して!」とお願いしておきました。

⑥FindVoice

ある人物の声のデータを約10分分与えると、それを学習し、動画などからその人物の発話シーンを検出することができるようになります。精度も非常に高くて素晴らしかったです。

Data Augmentationを駆使しているため、与えるデータ量も10分程度でいいという点が非常に実用的だなと思いました。

team25 demo

おわりに 

面白そうだなと思った方はおそらく来年度も開講されると思うのでぜひ受講してみるといいと思います!

deeplearning.jp

※アプリケーションの概要と公開されているリンクしか載せないようにしましたが、載せないで欲しいとか間違っているとかあれば編集するので教えてください。

Kerasで転移学習してSNSの画像を分類した話

授業でInstagram, Twitter, Facebookの画像を分類するアプリケーションを作成しました。

データ収集

instagram

まとめサイトでまとめられている、一般人の有名インスタグラマーのidを集め、その人たちの画像を約4万枚集めました。

twitter

1000RT以上、1000Fav以上の画像付きツイートの画像を約1万5千枚集めました。

facebook

これはチームメンバーがやってくれたのですが、友達をひたすらたどって画像を集めたようです。 結果として約1万5千枚集まりました。

モデル作成

フルで学習させると精度が中々出なかったので、ImageNetで学習済みのVGG16を使って転移学習をしました。転移学習なので、画像は結果的に3000枚ずつ、合計9000枚(training: 8100枚, validation: 900枚)を使いました。 転移学習はkerasを使うとめちゃくちゃ簡単にできます。

input_tensor = Input(shape=(100, 100, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

# FC層を構築
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.2))
top_model.add(Dense(3, activation='softmax'))

# VGG16とFCを接続
model = Model(input=vgg16.input, output=top_model(vgg16.output))

# 最後のconv層の直前までの層をfreeze
for layer in model.layers[:15]:
    layer.trainable = False

# Fine-tuningのときはSGDの方がよい
model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

軽く解説すると、まず、今回は入力画像を100×100にしました。そしてカラーなので、Inputのshapeは(100, 100, 3)です。 続いてVGG16のモデルを読み込んでいますが、今回は転移学習するので、全結合層の部分は入りません。したがってinclude_top=False, そして、imagenetで学習済みの重みを使うのでweights=’imagenet’です。 そして、全結合層を構築して、先ほどのVGG16と接続しています。今回は、Instagram, Twitter, Facebookの3値分類を行うので最終層の出力は3になっています。 全結合層以外の部分は学習されてほしくないのでfreezeしています。(参照: https://keras.io/ja/getting-started/faq/#freeze

結果

f:id:wakanapo:20180123132205p:plain

epochによるaccuracyの変化

validationのデートセットで約68%ほどの精度を出すことができました。

http://35.190.172.104/で実際に試すことができます。

webアプリケーション

flaskを使ってサーバーを立てました。 これは特に問題なく動いたので、herokuでデプロイしようとしましたが、”30秒ルール” (参照: https://devcenter.heroku.com/articles/error-codes#h12-request-timeout )に引っかかってしまうようでうまく動きませんでした。 次にGoogle App Engineを試してみました。無料枠のstandard版だとpython2.7しかサポートされていません。キレそう。幸い完全に互換性のあるコードだったのでPython2.7でも問題なく動きました。ですが、GAEでは純粋なPythonしかサポートされていないそうです。numpyはbuilt-inとしてサポートされているようですが、OpenCVやKeras(Tensorflow)が使用できないので諦めました。 結局、Google Compute Engineを使ってサーバーを立てました。無料枠だけではメモリが足りなかったのですこしメモリを足しました。

写真が投稿されてから、学習した重みを読み込み推論を行うようになっているのでレスポンスが結構遅いです。続けて2枚目、3枚目の写真を投げた場合は、すでに重みが読み込まれているので少し早くなります。要改善と言った感じです。

おわりに

Deep Learning Day 2018でポスター発表をしました。

www.slideshare.net

https://github.com/wakanapo/SNS_clissfication/blob/master/vgg16.ipynb

参考

http://aidiary.hatenablog.com/entry/20170131/1485864665