ロボットと趣味と自堕落と

ロボットの事なんか一言も書いてない

M5Stack GrayとSit2Goを接続するワイヤハーネスを作った

配線整理

inside-my-box.hatenablog.com

前回の記事で、FlexispotのSit2GoをM5Stack Grayを使って拡張しました。
その時は、ブレッドボードに抵抗やジャンパワイヤを挿して、Sit2GoとM5Stackを接続していました。
このままでは使いにくいので、接続をコンパクトにまとめるために今回はワイヤハーネスを作ります。

配線の確認

Sit2GoとM5Stackの配線を再掲します。
Sit2Goからは2本線の信号線が出ています。
図中の赤線がパルスの電圧を出しており、黒線がグランドです。
これをM5Stackに接続するのですが、単に赤線をGPIOに接続してもPCNTがパルスを捉えてくれません。*1
そのために、外部プルアップを行い、M5Stackの3.3Vとパルスの信号線を10kΩ抵抗を介してつなぎます。
これらの配線のために基板を作るのは少々手間なので、コネクタなどを使ってケーブルを作成します。

Sit2Goからは、元のLCDユニットに接続するために上図のようなJST SM-2Pコネクタのプラグ側が出ています。
JST SM-2Pコネクタはwire-to-wireのコネクタとして市販されているので、これのレセプタクル側を用意して接続します。 *2

M5Stack GrayのGPIOはQIコネクタで接続可能です。
今回使いたいポートのGND、3.3V、G36はM5Stackの同じ面に並んでいます。
QIコネクタは1pinだと曲がりやすいし抜けやすいので、(少し勿体ない気もしますが、)G36~GNDに6pinのQIコネクタをつなぐことにします。 *3

外部プルアップの配線のためには、パルスの線を分岐してプルアップ抵抗を接続する必要があります。
信号線の分岐には様々なやり方がありますが、手軽にできる方法を探します。
プルアップ抵抗は、市販の抵抗入りジャンパワイヤのように、配線材の途中にリード抵抗をはんだ付けすることにします。

必要部品と工具の購入

前述の配線の確認で、必要な部品がある程度見えてきました。

  • JST SM-2Pコネクタ(ハウジング、ピン)
  • QIコネクタ(ハウジング、ピン)
  • 信号線分岐パーツ
  • 10kΩ抵抗
  • 熱収縮チューブ(プルアップ抵抗はんだ付け部分の被覆用)

他にも、家に置いてある工具が古くなっていたり足りないものがあるので、この機に新調することにしました。

  • ワイヤストリッパー
  • 圧着工具
  • ニッパー

信号線分岐パーツには色々なものがありました。
車の電装系のカスタムなどで、信号線分岐パーツがよく用いられるようです。
色々調べてみて、下記のワイヤスプライスコネクタが使い勝手が良さそうだったので、これを使うことにしました。

jp.rs-online.com

引用元: https://docs.rs-online.com/337e/A700000010224750.pdf

分岐したい信号線の先にこのコネクタをつないで、コネクタに新たに配線材を被覆を剥かずに挟んだ状態で外殻を閉じてあげれば、被覆が勝手に剥けて、T字の分岐になるようです。便利~。

Amazonで電子工作用の部品を買うのはあまり良くない*4のですが、趣味DIYという事と、納期や他に買いたいものがある事を考えて、Amazonで全部調達することにしました。
以下に購入物のリンクを示します。(※全てアフィリエイト付きのリンクになっています。)

あと、勢いで以下の工具も買ってしまいました… *5

完成品

上図が作ったワイヤハーネスです。
最初の配線図のように、Sit2GoのPulseとGNDに繋がり、PulseはT型分岐コネクタで分岐され、片方はGPIOに、もう片方は10kΩの抵抗を挟んで3.3Vに繋がっています。
余談ですが、T型分岐コネクタは、Amazonで買ったせいか配線材を挟むだけでは被覆を剥くことができなかったので、ワイヤストリッパーで配線材の途中だけ被覆を剥いて芯材を露出させて挟み込みました。

Sit2Goにつなぐとこんな感じ。
気が向いたらちゃんと固定する台座も作ろうと思います。

感想

久しぶりにコネクタ作ったりはんだ付けしたりしました。
ミスって圧着端子を2、3個無駄にしちゃったし、GNDとその他の配線材の長さが異なっていてだいぶ不格好になっちゃいました。
こういうのも、いつか家庭で気軽にロボットがやってくれるようになるといいなあ。

fit2goのバグ

ワイヤハーネスの動作確認をしていて気付いたのですが、現在のfit2goのコードのワークアウト稼働時間の処理がおかしいようです。
本来なら、ペダルを漕ぎ始めてからタイマーが動き始め、ペダルを漕いでいる間だけ時間が経過するはずです。
しかし、現在のファームウェアでは、M5Stackの電源を点けると同時にタイマーが動き始め、ペダルを漕いでいない間も時間が経過しているようです。
おそらく、色々機能を追加したり修正したりしているうちに、ミスってGeminiが変なところを弄ったんだろうと思います。
こちらは次のアップデートで直そうと思います。

*1:前回の記事で触れ忘れましたが、内部プルアップでは駄目でした。

*2:凹形状のハウジングがピンコンタクト側でレセプタクル、凸形状のハウジングがソケットコンタクト側でプラグです。一瞬混乱しましたが、JSTのカタログを見て確認しました。https://www.jst-mfg.com/product/pdf/jpn/SM.pdf?6822b3cbb0ed6

*3:ただし、6pinのうち使うのは3pin分だけです。

*4:偽物や低品質のものが多いので…

*5:工具ってなんでこんなに魅力あるんだ…

Flexispotのフィットネスチェアを買ったのでAIに改造してもらった

事前注意

この記事では、趣味開発としてFlexispotのSit2GoをM5Stackで拡張したことについて記載しています。
記事中に出てくるGithubリポジトリなどはAIエージェントサービスを使って作成されました。
コードは予告なく変更されることがあります。
公開されているリポジトリを使って問題が発生しても、作者は一切責任を取りません。
ご利用の際は自己責任でご利用ください。
また、製品の権利者から指摘があった際には、権利者の指示に従いコードや記事を非公開にする可能性があります。
予めご了承ください。

まえがき

実は社会人になってから10kgぐらい太りました。
学生時代も体重は右肩上がりで、卒業する頃にはすっかり肥満だったのですが、そこから更に10kg増えました。
原因は運動不足です。
学生時代は家と大学が2.5kmぐらい離れていて、毎日自転車で移動してたので、少ないながらも運動してました。
しかし、今は起きている間のほとんどを座って過ごしています。
起きて机に向かって、夜に寝るという具合です。
その間ほとんど立ち上がることがありません。
学生時代から使っていた自転車も廃棄しました。

座りすぎは良くないという話がありますが、体に異常が出ないとあまり実感できないものです。
2年ほど前から足底筋膜炎のような症状が出ており、歩くと痛いです。
体重を支えられなくなったのか、膝も痛みが出ています。
これはかなりマズいと思って、座りながら運動できるものを買うことにしました。

Flexispot Sit2Goを買った

ほとんど座り仕事なので、フィットネスバイクを買うことにしました。
一般的なフィットネスバイクはハンドルがついているため、机と組み合わせられません。
色々探して、電動昇降デスクなどを売ってるFlexispot(Loctek)からハンドルなしのフィットネスバイクが発売されているのを見つけました。
www.flexispot.jp

www.flexispot.jp

残念ながらV6というモデルは販売終了しているとの事だったので、Sit2Goというモデルを買うことにしました。

これが届いたものです。
座面はかなり高い位置にあるので、電動昇降デスク必須です。
本体部分にLCDユニットがついており、ペダルを回すと運動に関する情報が表示されます。
表示される内容は以下の通りです。

  • 累積運動時間
  • 速度
  • 移動距離
  • 消費カロリー
  • 累積移動距離
  • RPM

使ってみた感じでは、使い勝手は非常に良く、手軽に無理のない運動ができました。
運動するとすぐに効果が出て、足裏の痛みがかなり軽減されました。
使い続けられれば、体重を落とすのにも役立ちそうです。

このままでもいいのですが、少し不満があります。
LCDユニットには色々情報が表示されていますが、LCDユニットからバッテリー(乾電池)を抜くと記録が全て消えてしまいます。
また、せっかく運動しているのにフィットネス管理アプリなどに情報を共有できないところも勿体ないです。 そこでなんとか拡張できないか検討することにしました。

Sit2Goを拡張する

拡張方針

フィットネスチェアを拡張するにあたり、以下の実現を目的としました。

  • フィットネスデータの計測・計算と記録
  • ウェブアプリへのデータ配信
  • Google FitやGoogle Health Connectなどのフィットネスデータ管理アプリへのデータ共有

これは、フィットネスバイクとWi-Fi接続機能を持つマイコンで実現できそうです。

上図は構成の概念図です。
左下のフィットネスバイクとWi-Fi機能を持つマイコンを接続します。
マイコンで運動データの計測と記録を行います。
同時にWi-Fiにも接続し、計測データを配信します。
配信されたデータはインターネットを介して、ウェブサービスのサーバに送られます。
サーバでは、受信したデータを記録・ブラウザで表示・フィットネスデータ管理アプリへ共有を行います。
こうすることで、前述の不満点を解消できそうです。

作成にあたって

最近AIエージェントのコーディング能力がすごいらしいです。*1
Gemini Advanced/ChatGPT/Github Copilotなどを使っていますが、驚くほどいろんなことをしてくれます。

gemini.google chatgpt.com github.com

現時点ではどれも完璧とは言えず、微妙なところやイケてないところはかなりありますが、会話からコードを作るのはそれなりにできそうです。
今回作成するのは主に以下の3つです。

ファームウェアの作成はほんの少し経験はありますが、石ごとに色々書き方が違ったりして結構面倒です。
また、ウェブアプリに関してはFlaskでローカルサーバを立てて簡単なものを作成した経験しか無く、正直に言って得意ではありません。
そこで、今回はファームウェアとウェブアプリをAIエージェントに作ってもらうことにします。

分析

フィットネスバイクから「ペダルを漕いでいる」という情報を取得する必要があります。
そこで、分解できるLCDユニットを分解してみて、何のマイコンが使われているかLCDに繋がるICを調べてみました。
残念ながら型番を調べても出てこなかったので、loctekのカスタム品かもしれません。
信号を直接見てどんなデータが得られるか確認します。

Sit2Goを組み立てるときにLCDユニットと本体を線でつなぐので、ここから信号が出ている可能性があります。
線は2線なので、1つはGNDで、もう一つが何かです。
候補としては以下の4つが考えられます。

  1. 単方向シリアル通信
  2. I²C
  3. パルス信号
  4. 独自規格

ICもカスタム品っぽいし、4の独自規格だったらお手上げですが、淡い期待を抱いて確認してみました。
線を引き出して、ペダルを回したときの電圧の変化を確認したところ、3の「パルス信号」でした。
一安心です。

パルスは上図のように、ある区間で0Vになり、それ以外の区間では約3.7Vとなっていました。
ペダル一漕ぎでパルス波が1個出てくることがわかりました。
これを捉えれば、元のLCDユニットで表示されていたような情報は求められそうです。

ファームウェアをGeminiに作ってもらう

パルスを受け取って運動データを計算したり配信するマイコンファームウェアを作ります。
ブラウザを開かなくてもデータが見れたほうがよいでしょう。
そこで、M5Stackを使うことにします。
M5StackはESP32が使われているので、ESP32用のファームウェアを作成します。
ファームウェア作成はGemini Pro 2.5に依頼しました。

ファームウェアには以下の機能をもたせます。

  • パルスカウンター
  • 運動情報の計算
  • 計測情報の記録
  • Wi-Fi接続機能
  • HTTPまたはHTTPSでデータを配信する機能

パルスカウンターはESP32のPCNTが使えるとの事なので、下図のように10kΩ*2のプルアップ抵抗を介してM5Stack、Sit2Go、シリアルモニタ用のPCを接続しました。

表示する運動情報には以下のものを選定しました。

  • 経過時間
  • RPM
  • 速度
  • 移動距離
  • 消費カロリー
  • METs
  • 累積経過時間
  • 累積移動距離
  • 累積消費カロリー

フィットネスバイクからはパルスしか取得できないので、各種運動情報はパルスから求める必要があります。
RPMはパルスから計算できるので、その他の情報はRPMを用いて求めました。
計算は以下の変数を用いて計算します。

  •  N: 計算間隔中に検出されたパルス数 (および回転数。1パルス=1回転を前提)
  •  t: 計算間隔の時間 (秒単位)
  •  R: 毎分回転数(RPM
  •  k_d: 1回転あたりの進む距離 (メートル単位、定数)
  •  v: 現在の速度 (km/h単位)
  •  \Delta D: 計算間隔中に進んだ距離 (km単位)
  •  k_C: カロリー計算係数 (定数)
  •  r_C: 現在のカロリー消費率 (kcal/秒単位)
  •  M: METs (運動強度)

なお、 k_d k_Cはわからないので、Sit2Goの信号線をLCDユニットとM5Stackの両方に繋いで、パルス値とLCDユニットの値から求めました。

 \displaystyle 
\begin{align} 
R &= \frac{N}{t} \times 60, \\
v &= \frac{R \cdot k_d \cdot 3.6}{60}, \\
\Delta D &= \frac{N \cdot k_d}{1000}, \\
r_C &= k_C \cdot R, \\
M &= \begin{cases} 
1.0 & \text{if } v < 1 \\ 
3.0 & \text{if } 1 \le v < 10 \\ 
4.0 & \text{if } 10 \le v < 16 \\ 
6.0 & \text{if } v \ge 16 
\end{cases}.
\end{align}

これで各種情報は求められました。

続いてWi-Fi接続機能についてです。
Wi-Fi接続では、SSIDとパスワードを設定する必要があります。
M5Stackには3つのボタンがあるので、表示されたリストからSSIDを選択するなどは可能ですが、パスワードの入力が困難です。*3
SSID/パスワードの情報をM5Stackに与える一番簡単な方法は、「SDカードにSSID/passwordを記入したファイルを配置し、起動時にそれを読み込む」という方法があります。
しかし、パスワードを平文で配置するのはセキュリティ上良くありません。*4
そこで、M5Stackをアクセスポイントにして、ブラウザなどからアクセスし、SSIDとパスワードを書き込むことにします。

上図はAPモードでの手順です。
M5StackでSSIDスキャンを行った後、APモードを選択します。
するとM5Stackに設定されたアクセスポイント情報が表示されるので、PCやスマートフォンWi-Fi機能でこのAPに接続します。
接続して指定されたURL(ここではhttp://192.168.4.1/)にアクセスすると、先程スキャンしたSSIDが表示されます。
接続したいSSIDを選択し、パスワードを入力して送信するとM5Stackが自動的に再起動し、指定されたSSIDに接続します。
指定されたSSIDとパスワードはESP32のNVS *5 に保存されるので、次回から自動的に接続します。*6

以上でファームウェアの大まかな構成が決まりました。
以下のリポジトリがGemini Pro 2.5に作ってもらったものになります。
github.com

ほぼイメージ通りのものを作ってくれました。
AIすげ~。
頭使わずに完成品ができてしまったので、これに頼り切っちゃうとコーディング能力が落ちそうでちょっと怖い気もします。

ただし、作成過程で色々気になるところもありました。
顕著だったものとしては以下の問題点が挙げられます。

最初に与えた指示やコードに引きずられる

最初に与えた指示やコードがあると、会話の途中でその指示を変更したりコードを変えるように指示を出しても、最初の指示/コードをキープし続けようとする傾向が見られました。
例えば、Aという指示で作られたコードに問題があり、Bという指示を出してコードを作らせると、AとBを組み合わせた処理ができました。
Aを忘れてBを作るように指示すると、Aとは直接関係ないが重要な機能を勝手に削除して、Bのシンプルな実装を作るという挙動はよく見られました。

ハルシネーション

簡単に言うと嘘です。
私が経験したものは、依存ライブラリとして挙げられたものが存在しないというものでした。
まぁ、これはもはや仕方ない気もしますが、コーディングで発生すると結構辛いです。
加えて、ハルシネーションが発生した部分を指摘すると、結構強気で反論してきます。*7

ハルシネーションとは違うかもしれませんが、下記のような問答もあります。

私: αを実現するコードを実装してください。
Gemini: はい、αを実現するために手法Xで実現しました。
私: Xというやり方が実装されましたが、これはp, q, rという理由で間違っています。Yというやり方が適切ではないですか?
Gemini: そのとおりです!αの実現にはYが適切です。Xにはp, q, rに問題があり、αの実現には適切ではありません。よろしければYで実装しましょうか?
私: (は?じゃあなんでX実装したんだよクソか?????)

ひどいときには「私は最初からXよりもYがいいと言ってました」のような応答もあり、しれっと結論をすり替えるみたいなのも見られました。
結構ストレス貯まるので、なんとか上手い回避方法が知りたいです。

レベリングミス

一言でいうと、「全体の目的に対して、各機能の実装がチグハグで全体と統一感がない」感じです。
今回のファームウェアを構成するにあたって、複数の機能が存在します。
その各機能の実装が、それぞれ極端に複雑だったり、完成基準に満たないほど低レベル(簡易実装)だったりしました。
そのため、結局ユーザが確認して、細かく指示を出す必要がありましたが、ここで先程の「最初のコードに引きずられる」という挙動が出てきて、修正がかなり大変でした。

ウェブアプリ作成

Geminiはチャット欄とエディタを行き来して結構辛かったし、前述の問題点もあったので、ウェブアプリは別のAIエージェントを使うことにしました。
調べてみると、VS Codeなどで動くものとして、Clineなるものがありました。
これは、VSCodeからGPT、Gemini、Claudeなど様々なエージェントを切り替えて使えるものらしいです。
また、コードの編集も自動でやってくれるそうなので、ユーザがコピペする必要がないそうです。
github.com

試してみたのですが、初期設定の途中から残高不足という表示が出てしまい、それ以上使えませんでした。*8
課金したらいいのですが、性能が不明なので別のものを使うことにしました。

Github Copilotは数年前からFreeプランのユーザでも使えるようになっています。
更に、最近のアップデートでGithub Copilot AgentというAIエージェント機能が追加されました。
フリープランのユーザは、Claude 3.5 Sonnetも使えるみたいです。
docs.github.com ウェブアプリにはGithub Copilot AgentのClaude 3.5 Sonnetを使って見ることにしました。

上記が完成したウェブアプリの画面です。
リアルタイムメトリクスに現在の瞬間的な計測値が表示されます。
セッション履歴には、時系列グラフでSpeedとRPMを表示しています。
また、その日のサマリーや、累計記録なども表示されています。
他にも、Google Fitとのデータ連携や、カレンダー機能もついています。
求めていたイメージ通りのものを作ってくれました。
AIすげ~。

Gemini Pro 2.5で感じていたストレスはほぼ無く、最初の1回でほとんど完成品が出来上がりました。
不足している部分やバグに関しても、ターミナルの実行結果を自動で認識し、適切な修正を自動で行ってくれました。
あと、普通に解釈能力とコーディング能力が高いし、Gemini Pro 2.5では感じられなかった「バランス感」が非常に高いように感じました。
これは課金してもいいかも。

ちなみに、完成したものは下記においてあります。
github.com

Renderにデプロイするように作ってもらいましたが、Renderではまだ試していません。
local_testブランチで、ローカル環境で動作確認をしていますが、mainとは差分があるので、多分Renderで使うにはもっと修正が必要です。

完成動画

作ったものを実際に動かしてみた動画を作成しました。
この動画もVeo2とかのAIエージェントで作れればよかったのですが、作れなかったので手動で作っています。

youtu.be

感想

AIすげ~

*1:個人的には、"AI"という名称は少し抵抗がありますが、「基盤モデル」もなんかしっくりこないので、抵抗は諦めて大人しく”AI”と呼ぶことにします。敗北…

*2:家に無かったので3kΩを3つ並列+3つ直列で繋いで10kΩにしました。

*3:キーボードを表示してボタンで1文字ずつ選択…という方法もありますが、大変です。

*4:暗号化/復号化もありですが、SDカードに書く前に暗号化が必要になり、手間が増えます

*5:不揮発メモリ

*6:NVSの中を見られたら平文で保管されてるのでセキュリティリスクはあります

*7:「私は存在を確認しています」とか「私からはアクセスできます」とか。

*8:ある程度は無料と書かれていたのですが、今はそうではないのかも

転職します

まずはお礼

先日、唐突にこんなツイートをしました。

非常にありがたい事に、多くの反応を頂き多数のお声がけを頂きました。
個別にご連絡させていただいた方々もいらっしゃいましたが、改めてここでお礼を申し上げます。
本当にありがとうございました。
ありがたいことにTwitterでお声がけを頂いた中から転職先もみつかったので、無職にならずに済みました。

今回は、せっかく転職活動を経験したので今後のためにも経緯や反省などを書いていこうと思います。

元の会社について

外資系のメーカーです。
いわゆる中央研究所のシステム系の研究部署で仕事をしていました。*1

異分野交流も含めて自由に研究したい人にとっては非常に良い会社だったと思います。
会社の文化や人や環境はかなり気に入っていました。
例えば、メイン業務以外にも好きなことを自由に研究する事を奨励する文化があったり、社内でハッカソンが開催されたり、定期的なポスターセッションがあったりと、自分の成果を発表して交流する機会も多くありました。
人もかなりユニークで知的でおおらかな人が多く、博士号を持っている方も多くいたためか、知らない分野についても詳しく聞くことが出来たりしました。
また、ほぼ毎週海外のチームと会議をする事があり、英語力を鍛えるいい機会にも恵まれました。

外資系とはいえ昔から日本にある企業なので、基本的には伝統的な日本企業っぽい会社で、その精神や文化として外資系企業っぽい面を持っていたと思います。
やるべき事はそれなりにありましたが、それでものびのびと仕事出来て非常に気に入っていましたし、今でも気に入ってます。

退職

残念ながら、そんな最高な会社を退職する事になってしまいました。
詳細は伏せますが*2、簡単に言うとポストが消えることが決定しました。
なお、ポストの消失については僕が悪い事をしたとか、能力が足りなかったとか、部署や会社の業績が悪かったとかではないのでご安心を。

それまで「外資系とはいえ、なんだかんだ言って伝統的な日本企業だな」と思っていたのですが、皮肉なことに今回のことが一番外資系企業っぽい雰囲気を感じる動きだったと思います。
それにしても、入社1年ちょっとで転職する事になるとは思ってもいなかったので、ポスト消失の事が発表されたときには相当驚きました。
その日はもう仕事にならないので、同期と「酒でも飲むしかねぇなこれ」と言って昼ごろに退社して飲みに行きました。
(引用: https://twitter.com/genbaneko_bot/status/1213434736938369025

転職活動でやったこと

ここからは転職活動で経験したことをベースに説明していきます。
そもそも、まともな転職は今回が初めて*3なので、何をどうすれば良いのかわかりません。
そこで、まずは調査をしようと偉大なるインターネッツで調べたり、転職経験者に聞いたり、転職エージェントに聞いたりしました。
得られた情報をまとめると、転職活動とは以下の事を行うとわかりました。

  1. 転職に必要な資料を用意する
  2. 企業の情報を収集し行きたい企業を決める
  3. 企業の入社試験(面接やテストなど)を受ける
  4. 待遇などの条件について検討し、必要なら交渉する
  5. 退職手続きを行う
  6. 入社手続きを行う

学生時代の就職活動とあまり変わりないですが、1で用意する資料と(4と)5が少し違うようです。
また、2や4に関しては転職エージェントを利用することで様々なサポートを受けることができます。これは学生時代の就職活動にはあまりなかった機能なので利用すると良いです。

1. 資料の用意

後述しますが、SNSを使おうが、エージェントを使おうが、自己応募しようが、資料の提出や面接はほぼ必ず必要になります。*4
そこで、以下の資料を用意しました。

  • 履歴書
  • 職務経歴書
  • 自己紹介+研究/仕事内容紹介のための10枚程度のスライド

履歴書は学生時代の就職活動でも作りましたが、職務経歴書は転職活動ならではだと思います。 これらは、色々なテンプレートがネット上に公開されています。 僕はリクルートエージェントさんのテンプレートをそのまま使いました。
スライドは勝手に作ったものです。学生時代の就職活動でも研究紹介のために作っていたので、スライドを使って説明した方がわかりやすいかと思い作りました。

職務経歴書について
履歴書は特に何も考える必要ないですが、職務経歴書はなるべく簡潔な文章でやったことを余すこと無く書くと良いらしいです。
職務経歴書は転職活動の途中で何度か書き直したので、最終版は最初の職務経歴書と大きく変わりました。*5
最終的に職務経歴書には以下の項目を書きました。

  • 職歴ごとの仕事内容(研究テーマと概要)
  • 担当した作業内容
  • 使える技術、プログラミング言語フレームワークなど
  • 成果と資格
  • 資格を裏付ける簡単なアピールストーリー
  • 学生時代の研究内容(学部~博士の各テーマのAbstract+画像1枚程度)
  • 業績一覧

資格について
職務経歴書などに書く資格ですが、アピールできるものは書くとよいと思います。
特に英語の資格は大体の人が持ってるはずなので、記載しておくとよいでしょう。*6

さて、この英語の資格ですが、定期的に英語資格を受けている方にとっては全く悩まない部分です。
しかし、僕は学部生の頃にTOEICを受けた以来全く資格を更新していなかったので少々悩みました。
転職活動を始めてからTOEICなどを受けるのは対策の時間などを考えるといい手では無いと思います。
更に、TOEICに限れば抽選もあるのでそもそも受けられるかとか、結果が出るまでに時間がかかるといった問題があります。
そこで、TOEIC以外で可能なら即日受験できて即日結果が得られる試験を探すことにました。
ネットで調べると、即日受けられる試験としてCASECやVERSANTなどがありますが、僕はEFSETという無料で受けられるものを受験しました。

EFSETは50分間の試験でReadingとListeningの技能を測れます。
試験は自宅で受けることができ、結果はすぐに表示されてLinkedInとかの証明書も発行してくれます。
試験結果の信憑性*7については、EFSETを運営している団体がかなり研究しているとの事で、全くのデタラメという事は無さそうです。
僕の結果はC1 Advancedという結果だったのでそれなりに良い結果だったと思います。
ただし、EFSETのTOEIC換算点は少々疑問があります。
僕の結果をTOEICに換算すると945-990点となるらしいのですが、流石にそんな点数は取れ無いと思うのでおそらく800点台ではないかと思います。
また、EFSETは本来何度も受験して自分の平均的な能力を計測することが推奨されているので、余裕があれば何度か受験したほうがよさそうです。

資料のレビュー
職務経歴書が出来上がったらいきなり企業に提出するのではなく、1日ぐらい寝かせましょう。*8
リラックスした状態で自分が書いた文章を改めて読むと、誤字脱字がみつかったり、より良い表現がみつかったりします。
場合によっては、構成のまずさに気づくことができ、書き直すことが出来ます。

それらの修正を終えたら、次に信頼できる誰かにレビューしてもらいましょう。
僕は転職エージェントにレビューしてもらいました。
基本的には修正する必要が無いとの事だったので、うまく書けたんじゃないかなと思います。
実際、書類審査で落ちる事は殆どなく各企業や転職エージェントからは高評価を得ることが出来ました。

自己紹介+研究紹介スライドについて
これは必須ではありませんが、作っておくと面接の時に話を進めやすいし面接官の方も質問しやすいかと思います。
内容は、履歴書+職務経歴書の補助です。
構成は自己紹介1枚、研究テーマ1つにつき1枚説明(1テーマ毎に動画1つ+簡単な説明)、趣味について1枚という形です。
特に、動画を埋め込む事は強力です。言葉や図以外で動くものでアピール出来ます。

スライドを使うことで、カジュアル面談では雑談混じりで研究説明ができ、スキルセットの証明や成果を説明出来ます。
転職エージェントを通した応募での面接でも、スライドベースで話をする許可が貰えれば自己紹介で質疑応答につながる説明ができ、相手も質問しやすそうでした。

2. 企業情報を収集する

いよいよ本格的に転職活動らしい活動です。
思いつく手段を使って企業の情報を収集しました。

  • SNS
  • 転職サイト・エージェント
  • 知人・友人

SNS
TwitterとLinkedInを使いました。
TwitterはちゃんとTLを育てていると、自分と近い分野の人が集まるため、転職活動でも比較的マッチ度が高いお話が来ます。
おそらく、Twitterで形成されるクラスタとエンジニアの相性が良いからでしょう。
多くのエンジニアは、日常的な趣味、技術的な話題、成果物、にゃーんなどをツイートします。
これらのツイートの多くは、言外の共通認識のもとに行われることが多いため、お互いの技術レベルや性格などを推し量る事にも使えます。
そのようなツイートを繰り返すことで、近い分野の人や興味を持ってくれた方が周りに集まり、自然とその分野の情報が集まってきます。
この情報の中には、求職や採用の情報も含まれているため、転職活動ツイートをすると拡散され、近い分野の人が採用情報の連絡をくれます。
そもそもある程度の共通認識を持つ集団から共有される情報なので、頂いた情報を選別する労力をかなり低く抑えることが出来ます。
技術という共通言語を持つエンジニアは、自分の専門分野のクラスタに属して活動することで、求職時にはクラスタ内から自分と近い仕事を得られる可能性が高くなるのではないかと考えられます。
実際、転職活動のツイートをしたときは、知り合いから2~3件ほどお誘いがあったら上出来と考えていたのですが、蓋を開けてみると非常に近い分野のお仕事について多くのお誘いを頂くことが出来ました。
Twitter最高。

他にも、SNSを用いた転職活動というと有名なのはLinkedInです。
かなり前にアカウント自体は作っていたのですが、今回の転職活動で初めてまともに整備しました。
整備と言っても、基本的にはプロフィールに職務経歴書や履歴書の内容を書いて、同じ会社の同僚や他社の知り合いや研究室の後輩などとつながった程度です。
LinkedInを使った最大の理由は、海外の企業や外資系国内企業にリーチするためだったので、プロフィールはすべて英語にしました。
結局、連絡が来たのは海外のヘッドハンターや国内外の転職エージェントばかりでしたが、数人とビデオチャットで話をするといろんな企業の情報が聞けました。
残念ながらLinkedInは整備したのが遅かったのもあり、Twitterほど強力なツールにはなりませんでしたが、ちゃんと使えばそれなりによいツールになりそうです。
Twitterとの大きな違いは、LinkedInは持ってる資格やスキルテストの結果と、つながりの広さが大きく影響しそうな点だと思います。*9

転職サイト・エージェント
今だにあんまりちゃんと理解してませんが、転職サイトやエージェントはいくつか有名なものがあるようで、何でも良いから適当に登録するというのではあまり効果が無いようです。
僕は下記のサイトを利用しました。

各サービスによって強みが異なるので、僕は以下のように使い分けていました。

  • リクルートエージェント: 転職活動の基礎確認、キャリアの棚卸し、書類の添削
  • JAC Recruitment: 国内大手企業の情報収集と応募
  • Hays Japan、RGF: 海外企業、外資系企業の情報収集と応募
  • ビズリーチ: 国内企業の情報収集と応募
  • 博士情報エージェント: 研究職限定の仕事情報の収集

実際には、ビズリーチや博士情報エージェントはほとんど利用せず、リクルートエージェントで書類準備、JAC、Hays、RGFで情報収集と応募という形で使っていました。*10

転職エージェントを利用する場合は、エージェントの質も重要です。
中には全然関係ない仕事を振ってくる方もいます。*11
エージェントも万能ではないし、僕の事を正確に知ってるわけではありません。
そのため、エージェントが持ってくる情報をレビューして返答してあげる必要があります。
少々面倒かもしれませんが、これをやることで徐々に精度が上がってきます。
機械学習のラベリング作業やハイパーパラメータの調整みたいな気持ちでやるとちょっと面白いです。*12

知人・友人
社内の同僚や先輩から情報をもらうのも手です。
僕は今回の転職活動で、お会いした事もないほどご年配の会社のOBの方などからもご連絡頂き、色々相談にのってもらうことが出来ました。
また、大学時代の友達や昔Twitterで知り合った同業分野の友人にも色々と助けて頂けました。ありがとうございます。

企業選定の基準
さて、情報収集を始めると非常に多くの情報が手に入り、どれが自分とマッチするか迷います。
その際に、仕事を選ぶ基準を定めておくと選定が楽になります。
僕は下記の基準を設定しました。

  1. 仕事内容: せっかくなので元々の専門分野である知能ロボット系の研究開発をやれる仕事を探しました。
  2. 報酬: お金は大切です。お金があると、プライベートでも新たな技術を手に入れるための自己投資が出来ます。
  3. 企業文化: 硬直した組織よりは、活発に新しい事に取り組んだり世の中の課題を自ら解決していこうという体質の企業を探しました。
  4. キャリアパス: 今後の事を考えると、対外発表で実績を積みたいと思っているので、対外発表などを積極的に行っている企業を探しました。

3. 入社試験を受ける

入社試験と言っても主に面接とウェブテストです。*13
企業によってどちらを重視するかが異なるので、可能な限り情報を収集すると良いです。エージェントを利用している場合は、過去の事例なども参考にして教えてくれるので割と正確な情報が手に入ります。

受ける企業がウェブテストを採用している場合は、主に能力検査と性格検査があります。
能力検査は言語と非言語とかがありますが、対策方法の紹介は世の中にごまんとあるのでここでは割愛します。*14
性格検査は種類がいくつかあるようですが、よく言われるのは「面接での回答と齟齬がないようにする」事だそうです。
このアドバイスは以下の二通りの解釈があると思います。

  1. 自分の考えに素直に回答する
  2. その企業が求める人物像になりきって回答する

1はボロが出にくいですが、自分でも把握できていない何らかの問題がある場合は、残念な結果になる可能性もありそうです。日頃から自分の思想と行動を分析して、必要なら自分の弱点を対策しておくと良いと思います。
2はおそらく試験突破率はかなり高いと思いますが、相当器用な人でないとボロがでる気がします。*15

面接は基本的に聞かれたことに対してポイントを抑えて簡潔に回答すればよいです。
しかし、「ポイントを抑えて簡潔に」なんて真面目にやろうとすると、シンプルになりすぎて自分の面白いところをアピール出来ない可能性があります。
その場合は、学会発表などの質疑応答対策でよく使われる手法が使えます。
それは「ツッコミどころや聴衆が気になるであろうポイントをあえて残す」という手法です。
前述のスライドを用意したのはこのためでもあります。すべて口頭で済ませるのは無理があるので、苦手なところは技術に頼りましょう。
それでもダメだったら、仕方ないです。運が悪かったか相性が悪かったのでしょう。気にしても意味ないです。

4. 5. 6. 条件交渉とか退職・入社手続きとか

条件交渉についてはあまりわかりません…
エージェントを使って得た内定であれば、担当エージェントが交渉してくれるそうです。*16
せっかく転職するのに現在の生活水準を落とす事になるとちょっとつらいので、問題ないか確認して必要なら交渉したほうが良いと思います。

僕はTwitter経由で頂いたお話に自己応募したので、エージェントによる交渉は使えませんでした。
そこで、給与、勤務地、居住地、賞与などを聞いて自分で簡単な確認をしました。
そこでは、居住予定地の家賃レンジと、賞与を考慮した収入から税金を引いた年収レンジをプロットして、現在の収入との比較を行いました。
簡単なのでこれぐらいはやっておいたほうが良さそうです。

退職手続きや入社手続きは、遅れないように必要な資料を用意する手続きをしましょう。
特に入社時に提出する書類には発行までに時間がかかる資料もあるので、提出が遅れる場合はその旨をちゃんと伝えましょう。

転職活動の反省とこれから

転職活動の反省

初めての転職活動でしたが、思い返してみると学生時代の就職活動もスカウト系や逆就活系のサイトを利用していたので、いわゆる普通の就職活動は今回が初めてでした。
そのため、失敗したと思う事もいくつかありました。
特に、下記の事についてはもっとうまくやるべきだったなと思っています。

  • 資料準備と公開できる成果物の用意
  • 選考タイミング調整
  • 連絡手段の管理

転職しようがしまいが日頃の活動を何かしらの記録に残しておけば、いざ転職というときにも今までの記録をまとめるだけで良いので、資料用意に時間をかけなくて済みます。
また、特にエンジニアに限った話では無いですが、業務外で公開できる成果物は何かしら用意しておくべきだったなと思います。
転職活動中にGitHubのアカウントを度々聞かれたのですが、学生時代は研究室の非公開リポジトリで開発していたし、就職してからは社内の非公開リポジトリで開発してたので、対外的に公開できるコードがほとんどありませんでした。やはり日常的に開発活動をするのは大切です。

選考タイミングの調整は、理想的には複数の企業の内定が同時に出揃うと良いです。
これは選考企業のスケジュールもあるので、簡単には出来ませんが人事面接などで現在の選考状況を伝えたり、エージェント経由でスケジュール調整してもらうなりしたほうが良かったなと思っています。

連絡手段の管理は具体的に言うとGmailアカウントを転職活動用に用意し、自動ラベル付けを外すという事です。
学生時代の就職活動時にはやっていたのですが、今回は急な転職活動という事もあってプライベートのアカウントで転職活動サイトなどに登録してしまいました。
日々大量の連絡が来るので、メールの見逃しが発生したり、企業からの重要なメールなのに勝手にプロモーションタグがついて受信トレイに表示されなかったりといったトラブルが発生しました。*17
転職活動時には専用のアカウントを用意したほうが良さそうです。*18

これから

入社して1年経ったところで突然転職活動をする事になるとは思ってもいなかったので相当驚きましたが、元々5年ぐらいしたら転職を考えようと思っていたので、少し*19早まったと考えれば問題ないのかなと思っています。
元の会社も優秀で良い人達に恵まれて、たった1年少々でしたが刺激的でとてもいい経験が出来たと思っています。
唯一の心残りとしては、入社即リモートワークだったので去年から数えて20回程度*20しか出社しておらず、いまだに会社内の地理がわかっていないところです。*21

今回の転職活動で、ありがたいことに昔からやってみたかったテーマに取り組める企業から内定を頂き、その企業に行く事にしました。
学生時代から取り組みたかったテーマだったので、非常に楽しみです。頑張るぞい。

*1:どこの会社か知っている方は、秘密にしていただけると助かります。

*2:会社が公にしてないので

*3:研究員から現職になった事は厳密には転職ですが、元々新卒で現職に就くことが決まっていたので一般的な転職活動はこれが初めて

*4:特殊な採用ルートの場合、資料の提出や面接が無い場合もあると思いますが、僕は知りません

*5:最初の職務経歴書はシンプルに書きすぎでした…

*6:他と比較してマイナスにならなくて済むという意味です

*7:妥当性?

*8:論文と同じですね

*9:Twitterはつながる広さよりも所属クラスタの質が重要だと思います

*10:ビズリーチは大量に連絡が来るので選別が大変だったし、博士情報エージェントはほとんど情報が来なかった

*11:研究開発職を希望しているのに、コンビニの店長の話が来たときには流石に呆れましたが…

*12:人間なので学習能力が非常に高く、また、自己学習もするので何度かやってるとドンピシャな情報しか持ってこなくなったりします。すごい。

*13:中には口頭試問や、独自の能力テストを行っている会社もあります

*14:僕もちょっと不安だったので本を買って少し対策しました。

*15:僕は不器用なのでこの方法は採りませんでしたが、同期はこの方法でやってました。かなり器用だと思います。

*16:すげぇ

*17:本当に申し訳ございませんでした…

*18:そもそもGmailを使わないという手もある

*19:4年は「少し」か…?

*20:しかもほとんどモノを取りに行ったりしただけなので、平均滞在時間3時間程度

*21:もっと散歩しとけばよかった

近況報告

Q. 生きてますか?

A. 元気にツイッターしております.

久々の更新です.
なるべく毎日書こうと思っていたあのときの僕はどこへ消えたのか.

ともかく,久々のブログ更新なので,ブログを更新していなかった期間何があったのかと近況報告を書きたいと思います.

何があったか
  • 2019年3月: D3で修了できませんでした*1
  • 2019年4月: D4に進学しました
  • 2019年9月: 博士修了.博士(工学)になった
  • 2019年10月: 大学で研究員として就職
  • 2020年3月: 研究員退職
  • 2020年4月: 一般企業に入社
感想とか

*2は,大学生といえば人生の夏休み,とても楽しい,一生学生で居たい,などと思っていましたが,今では「もう学生はやりたくない」という気持ちのほうが大きいです.
思い返してみれば大学という場所に10年も居たんですね.
そりゃあ飽き性の僕がそう思うのも無理もないなと思います.

色々*3あって,D3では終われませんでした.
D4まで伸びてしまった理由はいくつも思い浮かぶのですが,忘れたいぐらいの話なのでここでは伏せておきます.
つくづく自己管理能力や学術的な能力がないなーと思います.
正直,「こんなんで学位もらって恥ずかしい」という気持ちのほうが大きいです.*4
学位論文も,正直な気持ちとしては読み返したくありません.
書き直せるなら書き直したいぐらいです.

ともあれ,曲がりなりにも修了できました.
両親をはじめ,指導教員,研究室の元同期や後輩,高校時代の旧友など,本当に数多くの人々に助けられました.
ありがとうございました.

学位を取ってからは,毎日が楽しかったです.
指導教員のご厚意*5で,同じ研究室で半年間だけ研究員として雇ってもらいました.
そこではD論のテーマとは異なる,新たなテーマをやっていましたが,今までやってきた事と少し系統が違う内容で楽しかったです.
たった半年間の研究員生活でしたが,学ぶことが多かったと思います.

なぜ研究員が半年間だけだったのかという理由にもつながるのですが,2020年の4月(今日)から,外資系材料メーカーに入社することになりました.
実は,2019年修了予定で就職活動をしていて,2019年4月に入社する予定だったのですが,修了が伸びてしまったため,このような形になりました.
当時は半泣きになりながら内定先の人事の方に頭を下げて,もう少しだけ待ってくださいとお願いしたのを覚えています.*6
ありがたいことに,内定先の方々から「入社は待つから,ちゃんと学位を取ってきてください」とのお返事を頂き,2020年入社となりました.

晴れて本日入社式を終えたのですが,今は新たな仕事に期待で胸を踊らせている感じです.
とても楽しみ.

これから

学生時代のことを振り返ると,後悔やそれに対する反省が非常に多いです.
いつまでもこの調子だと,今後会社に入ってもいつ首を切られてもおかしくないと思います.
冷静になって,着実に進んでいきたいと思います.

以上.
疲れた頭で書きなぐった散文なので,非常に読みにくいですが,近況報告でした.

*1:実績不足

*2:B1~B2ぐらい

*3:別にそんなに何かがあったわけではない

*4:一応自分のためにフォローしておくと,*新規性は*非常に高い提案手法でした

*5:多分このブログは見られてないと思う(思いたい)けど,本当にありがとうございます.

*6:30歳直前のおっさんの涙は醜い

機械学習による異常検知① ー正規分布に従うデータからの異常検知

はじめに

2年ぐらい前に下記の本を利用して異常検知をちょこっとやっていたのだけれど、気が向いたのでここに纏めていこうとおもう。 僕は確率統計苦手マンで、説明下手くそマンなので、間違っているところや説明が雑な点があったら指摘してください。*1

使う本

井手剛の『入門 機械学習による異常検知 Rによる実践ガイド』を参考に用いる。 なお、個人的にプヨグヤミングの練習でもやろうかなとか思っているので、コードはC++で書く。*2

異常検知とは

何らかの分布に従って生成されているデータから得られた規範を元に、新たなデータがその規範に従っているかどうかを判定し、規範から外れているものを異常とする仕組み。 書籍の言葉を使うと、

正常となるモデルをデータから作り、そのモデルから外れるものを異常とすること。

です。 詳しい話は本の1章に任せます。

異常検知の手順

1. 分布推定
正常なデータからモデルとなる確率分布を作り、分布のパラメータ(平均や分散など)を推定する。
2. 異常度の定義
正常からのズレ具合を定義する。例えば負の対数尤度など。
3. 閾値の設定
ホテリング理論などに基づいて、異常度に対する閾値を設定する。
4. 異常検知
定義した異常度を計算し、閾値よりも高い値を異常と判定する。

1変数正規分布に基づく異常検知

データの分布を推定する

異常な値が含まれていないとされるデータ*3 D=\left\{x_1, x_2, ..., x_N\right\}
正規分布に従うとする。
 \displaystyle \mathcal {N}( x | \mu , \sigma^2) = {\frac{1}{(2\pi\sigma^2)^{1/2}}} exp \left\{ -{\frac{1}{2\sigma^2}}(x-\mu)^2 \right\} \tag{1}
この分布のパラメータ \mu,  \sigma最尤推定で求めると
 \displaystyle \hat{\mu} = \frac{1}{N}\sum_{n=1}^{N} x_n \tag{2}

 \displaystyle \hat{\sigma} = \frac{1}{N} \sum_{n=1}^{N}(x_n-\hat{\mu})^2 \tag{3}
となる。

異常度を定義

負の対数尤度を異常度 a(x)と定義する。
(1)式の対数尤度を計算すると、以下のようになる。
 \displaystyle \ln{\mathcal{N}}=\frac{1}{2\hat{\sigma}^2}(x-\hat{\mu})^2+\frac{1}{2}\ln{2\pi\hat{\sigma}^2} \tag{4}
ここで xを観測値 x=x'とすると、ある観測値に対する異常度を計算する事ができる。
(4)式で観測値 x'に依存する項のみを抜き出し、2を掛けると、異常度 a(x')
 \displaystyle a(x')=\frac{1}{\hat{\sigma}^2}(x'-\hat{\mu})^2=(\frac{x'-\hat{\mu}}{\hat{\sigma}})^2 \tag{5}
と定義できる。

閾値を設定

  • ホテリング理論

1次元の観測データ D=\left\{x_1, x_2, ..., x_N\right\} の各観測値が独立に同じ分布 \mathcal{N}(\mu, \sigma^2)に従い、新たな観測値 x'も同じ分布に独立に従うとする。このとき、式(5)の a(x')の定数倍は自由度 (1, N-1) F分布に従う。すなわち
 \displaystyle \frac{N-1}{N+1}a(x')~\mathcal{F}(1, N-1) \tag{6}
特に、 N \gg 1のときは、 a(x')そのものが自由度1、スケール因子1のカイ二乗分布に従う。
 \displaystyle a(x')~\chi^2(1,1) \tag{7}

よって、閾値カイ二乗分布を元に決めれば良い。
つまり、カイ二乗分布において、 a_{th} \le a(x)の面積が \alpha\%になるときの異常度を閾値をすれば良いということ。
具体的には、例えば「閾値 \alpha=15.7\%となるように選ぶ」とすると、下図の青い領域の面積が 0.157となるように異常度の限界値を決めるという事となり、その時の異常度の閾値 a_{th}=2.0となる。 f:id:i-hako:20180301014137p:plain
このことを数式に表すと以下の積分方程式を解いて閾値 a_{th}を求める事となる。*4
$$ \displaystyle \begin{align} \alpha &= \int_{a_{th}}^{\infty} \chi^2(u|1,1) du \\ &=1-\int_0^{a_{th}} \chi^2(u|1,1) du \tag{8} \end{align} $$

実際のコード

#include <iostream>
#include <boost/math/distributions/chi_squared.hpp>
using namespace std;
using namespace boost::math;

double Uniform(){
  return ((double)rand()+1.0)/((double)RAND_MAX+2.0);
}

vector<double> GenerateData(int data_size){
  vector<double> data;
  // srand((unsigned)time(NULL));
  srand(100);
  double mu=0.0, sig=10.0;
  for(int i = 0; i < data_size; i++){
    double z = sqrt(-2.0*log(Uniform()))*sin(2.0*M_PI*Uniform());
    double val = 170.0+mu+sig*z;
    data.push_back(val);
  }
  return data;
}

double ChisqrSetCriticalValue(double dof, double los){
  chi_squared dist(dof);
  double p_val = quantile(complement(dist, los));
  return p_val;
}

double CalculateAnomaly(double mu, double sig, double val){
  return pow((val-mu), 2)/sig;
}

int main(void){
  // 正規分布に従う適当な正常データを生成
  vector<double> normal_data = GenerateData(100);

  // 分布のパラメータを推定
  double mu = 0.0, sig = 0.0;
  for(int i = 0; i < normal_data.size(); i++)
    mu += normal_data[i]/normal_data.size();
  for(int i = 0; i < normal_data.size(); i++)
    sig += pow(normal_data[i]-mu,2)/normal_data.size();

  // 異常なデータを生成して元データにくっつける
  vector<double> abnormal_data = GenerateData(3);
  for(int i = 0; i < abnormal_data.size(); i++){
    double data_value = abnormal_data[i];
    normal_data.push_back(data_value + 50);
  }

  // 閾値を計算 (α=0.01)
  double a_th = ChisqrSetCriticalValue(1, 0.01);
  cout << "a_th: " << a_th << endl;

  // 異常度を計算
  vector<double> anomaly_data;
  for(int i = 0; i < normal_data.size(); i++){
    double data_val = normal_data[i];
    double anomaly = CalculateAnomaly(mu, sig, data_val);
    if(a_th <= anomaly){
      cout << "index: " << i << " is abnormal data" << endl;
      cout << "value: " << data_val << endl;
      cout << "anomaly score: " << anomaly << endl;
    }
  }

  // 描画はお好きなように…
  // (csvで吐き出してgnuplotでもいいし、matplotでもいいと思います)
  return 0;
}

閾値を求める際に、boost::mathquantile()を使いました。 簡単に棄却限界値を求められるので楽です。

実行結果

f:id:i-hako:20180301024757p:plain

a_th: 6.6349
index: 100 is abnormal data
value: 234.823
anomaly score: 38.1338
index: 101 is abnormal data
value: 221.681
anomaly score: 24.1974
index: 102 is abnormal data
value: 224.632
anomaly score: 27.052

適当にデータ生成してしまったので、怪しい結果のやつもいますが、最後に付け加えた3つの異常データがすべて閾値の点線よりも上に存在している事がわかります。

おわりに

すごくざっくり説明したので、これを読んで「???」となった人がいるかもしれません。*5
実際のホテリング理論は結構複雑な証明を2、3個挟む必要があるのですが、力尽きたので割愛しました。*6
また暇な時に書きたいと思います。
今度は多次元正規分布に基づく異常検知について書いていきたいと思います。

*1:可能な範囲で対応します

*2:雑魚ードなのはご容赦…

*3:異常値が含まれている場合は事前にデータクレンジングなどを行う必要がある

*4:実際には直接計算する必要は殆どなく、計算ライブラリなどに頼れば良い

*5:ごめんなさい…

*6:はてブロなんでこんなに数式書くの面倒なの…

『独創はひらめかないー「素人発想、玄人実行」の法則』を読んだ

どういう本か

工学博士の金出武雄先生による、様々な研究者などとの交流や過去の経験から得られた「思考法*1」やその精神について述べた本。
世間一般にある「ハウツー本」や「自己啓発本」とはまた違った感じの本。

なぜ読んだか

数年前に本書を購入して、積読してたのだけれど、ここしばらく研究が行き詰まり、いいアイディアも出てこないので、「何か書いてねぇかな」という気分で手に取った次第です。
「気が向いたから」と言えばそれまでである。

金出武雄先生について

Wikipediaでも見てください。
「ロボット研究している人で金出先生を知らない人はモグリ」なんて言われるぐらいすごい人(だそう)です。
(ちなみに、僕は学部生の頃に研究室のボスから教えてもらうまで知りませんでした…)
OpenCV触った事ある人ならば、cv::calcOpticalFlowPyrLK()という関数を見た事があるかもしれないけれど、この関数で使われているLucas-Kanade法の考案者。
An iterative image registration technique with an application to stereo vision

本書の構成

4章から成っており、章ごとに小テーマが存在する。

1章

ここでは、「素人発想、玄人実行」という考え方について著者が過去に行ってきた研究から、半ば帰納的に「こういう思考・精神でいるとよい」ということについて述べている。
比較的「ハウツー感」のある章。

2章

2章では、コンピュータと人間を比較しながら、「問題解決能力とは何か。どのように獲得されるのか。」について述べている。また、問題解決能力と結びつけて思考力や記憶力についても述べられている。
メタな感じの内容が書かれている。

3章

成果を発表しても伝わらないことには意味がない。
ここでは、「説明する・発表する」ということに焦点を絞り、どのような発表方法が良いのか、論文と口頭発表のスタンスの違いや、英語力などについて著者の考えが述べられている。
本書で一番「ハウツー感」が高い章かもしれない。

4章

「組織の意思決定の早さ比較」について日本とアメリカを対比して、その精神性について述べている章。
上記3章とは少し毛色が異なり、過去のプロジェクトや、CMUの風習などを用いて比較を行っている。
よくある「日本ダメ。アメリカ万歳!」的な中身のない文章とは異なる。

各章の感想

  • 1章
    解決したい問題について、いかに「うまく単純化」し「良いシナリオを考える」かという話は改めて言われて印象に残った。
    素人のように(素直に)考えて、玄人のように(精密に)実行する」という考え方は、非常に重要であると共感できた。 というのも、僕は変なところで心配性であり、"余計な事"を非常によく考えてしまう癖がある。研究では細かい点が理論的でない事が気になってしまい、多くの時間を取られて失敗に終わる事がある。 KISS -"Keep It Simple, Stupid."というアプローチを大切にしたい。
    また、物事がうまくいかないときに、いかに「とりあえず最後までやっちゃおう」という気分に切り替えられるかが、物事を進める上で重要なのだなという事がわかった。

  • 2章
    問題解決能力がどのように養われるかという点について、日本式教育しか受けていない僕からすると、教科書の構成の違いなどの話は驚きだった。
    また、思考力や判断力は問題解決によって鍛えられるが、記憶力も重要な要素であるという話は納得がいった。
    確かに、毎回イチから全検索するよりは、パターン類似度の高い情報を抽出する方が効率は良いよね。

  • 3章
    おそらく、本書を読んだ動機とは別で、一番読みたかった内容かもしれない。
    伝わる文章やスライドを作るのが非常に苦手な僕にとっては、かなりためになる章だった。 「起承転結」や「流れを意識する」なんてことはもちろんわかっている。わかっているのだが、実際にはうまく書けない。
    そういう点について、読者や聴衆の関心度の変化を意識することでどのように書くと良いかという話が出たのは良かった。
    一方で、口頭発表におけるスライド構成については、本章の内容を意識しながらも、発表環境に合わせて変えるべきだとも思った。*2
    あと、英語に対する認識や訓練方法が金出先生と同じだったのは、肯定された気分になって非常によろしかった。

  • 4章
    「意思決定は早いに越したことはない」「責任逃れるために主張を控えるよりも、主張してしくじったら責任取ればいい」という感じの内容。 正直あまり実感できなかったが、昨今の「ニッポンすげぇ」論に対する警鐘としても受け取れる。*3

全体を通した感想

久しぶりに「読み物」としての本を読んだのもあって、一気に読めました。 また、読む前に抱いてた「研究うまくいかね~~~~~」みたいな感情が、いい感じに消化*4できた気がします。 非常に面白く、読みやすい内容なので、何かに行き詰まってる人や効率的な思考プロセスを得たい人は読んでみると良いと思います。

*1:むしろ哲学と言って良いような…

*2:卒/修/博論審査会でTEDみたいな発表は誰も求めていないのである。

*3:というかそういう内容が書いてある

*4:「昇華」ではない