エクサウィザーズ Engineer Blog

株式会社エクサウィザーズのエンジニアチームブログ

ロボット制御における特異点

エクサウィザーズMLエンジニアの柳元です。 あけましておめでとうございます(遅い)。
エクサウィザーズのRobotTechチームはこれまでにマニピュレータロボットを使って 粉体秤量 、液体秤量、 パレタイジング 、ピッキング、コンプライアンス制御などの動作を機械学習させることに成功してきました。 そして、これらの学習済みモデルを COREVERY によってデリバーしています。
学習と制御のフローを考えたりデバッグをする上で、念頭に置かなければならないことの1つとして、特異点の問題があります。今回はロボット制御におけるこの「特異点問題」についてお話しします。

ロボットの特異点(Singularity)とは?

特異点と聞いて何を想像するでしょうか?多くの人が 技術的特異点 を想像するかもしれませんが、数学・物理学・制御学においては
特異点(とくいてん、英: singular point、シンギュラー・ポイント)は、一般解の点ではなく特異解の点こと。ある基準 (regulation)を適用できない、あるいは一般的な手順では求まらない(singular) 点である。特異点は、基準・手順に対して「—に於ける特異点」「—に関する特異点」という呼び方をする。
とあります(Wikipediaより)。
ロボット制御における特異点は、構造的に制御できない姿勢を指します。軌道に特異点が含まれている場合、ロボットは特異点付近において高速に移動(暴走)し、そして特異点で停止してしまいます。 なので、制御する際にはこれを避ける必要があります。

ロボットの姿勢の表現

ロボットがどんな体勢になっているかの表現は、ふつう以下のいずれかを使用します。
  1. 関節変位 (Joint space) $q$: 関節の角度の値
  2. 姿勢 (Pose, Task space) $r$: TCP(Tool Center Point, ロボットの手先の位置)を表す3次元空間の値
例えば、URのような6DoFのマニピュレータは、6個の関節(joint)を回転させて姿勢(pose)を変化させることができます。
画像は公式サイトを元に弊社で注釈をつけたものです

この場合は関節変位$q$と姿勢$r$はそれぞれ \begin{equation} q = [\theta_1, \theta_2, \theta_3, \theta_4, \theta_5, \theta_6] \\ r = [x, y, z, r_x, r_y, r_z] \end{equation} というベクトルで表現できます。
例えばこのロボットのエンドエフェクターにグリッパーを取り付けて、物体のピッキングをさせる場合について考えます。 物体は深度カメラで撮影されていて、その位置$P=[x_P, y_P, z_P]$は既に計算されています。 あとはロボットのTCPを位置$P$付近にくるように姿勢を制御してグリッパーを閉じれば、物体を掴むことができます。
ただ、ロボットそのものにできることは基本的には関節を動かすことだけです。 目的地点の位置や姿勢を指示されても、関節をどう動かせば目的の姿勢になるのかがわかりません。 そこで運動学を考える必要が出てきます。

運動学

運動学(kinematics)とは関節変位$q$と姿勢$r$の関係を表す数式であり、
  1. 順運動学(forward kinematics): 関節変位$q$から姿勢$r$を求める, $r = f(q)$
  2. 逆運動学(inverse kinematics): 姿勢$r$から関節変位$q$を求める, $q = f^{-1}(r)$
の2種類があります。 上述のピッキングの例だと、逆運動学を使って$r$を$q$に変換する必要があります。

同次変換行列

順運動学$f$について知るために、まず同次変換行列(Homogeneous transformation matrix)について説明します。
3次元空間に原点座標系$O$と座標系$A$があり、点$Q$が座標系$A$上の $r_{Q}=[x_{Q}, y_{Q}, z_{Q}]$に存在していたとします。 ここで、座標系$A$を原点座標系$O$に対して$p=[x_p, y_p, z_p]$移動させ、さらに$R_{OA}$回転させます2。 移動と回転後の点$Q'$の位置$r_Q'=[x_Q', y_Q', z_Q']$は \begin{equation} r_Q' = p + R_{OA}r_{Q} \end{equation} となり、これは下のように書けます: \begin{equation} \begin{bmatrix} r_Q' \\ 1 \\ \end{bmatrix}=\begin{bmatrix} & & & \\ &R_{OA}& &p \\ & & & \\ 0&0 &0&1 \end{bmatrix} \begin{bmatrix} r_{Q} \\ 1 \\ \end{bmatrix} = H_{OA} \begin{bmatrix} r_{Q} \\ 1 \end{bmatrix} \end{equation} この$H_{OA}$を同次変換行列といいます。

リンクとジョイント

ロボットはリンクジョイント(関節)で構成されています。 人間の腕で考えると、脇や肘、手首が回転の中心があるジョイントで、ジョイント同士の間にある上腕や前腕がリンクです。
再びURについて考えると、リンクとジョイントは下の図のようになっています。 「ジョイントn」の関節角度は$\theta_n$で、TCPはリンク6の上にある点です。
画像は公式サイトを元に弊社で注釈をつけたものです

このように、ロボットは複数の座標系が連なりあって構成されていて、各ジョイントの関節変位と姿勢によってTCPの姿勢、つまり順運動学が計算できると予想できます。

Denavit–Hartenberg parameters

Denavit–Hartenberg parameters(DHパラメータ)は、上のような同次変換によってロボットの順運動学を計算する際に必要な4つのパラメータ$\alpha, a, d, \theta$を指します。
Wikipediaより引用

上の図のようにDHパラメータと座標系が決まっている時、座標系$n-1$から座標系$n$への同次変換は次のようになります: \begin{equation} T_{n}^{n-1}={\rm Trans}_{z_{n-1}}(d_n) \cdot {\rm Rot}_{z_{n-1}}(\theta_n) \cdot {\rm Trans}_{x_{n}}(a_{n}) \cdot {\rm Rot}_{x_n}(\alpha_n) \end{equation} ただし、 \begin{equation} {\rm Trans}_{z_{n-1}}(d_n)= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & d_n \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \hspace{30pt} {\rm Trans}_{x_n}(a_n)= \begin{bmatrix} 1 & 0 & 0 & a_n \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \\ {\rm Rot}_{z_{n-1}}(\theta_n)= \begin{bmatrix} \cos\theta_n & -\sin\theta_n & 0 & 0 \\ \sin\theta_n & \cos\theta_n & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \hspace{15pt} {\rm Rot}_{x_n}(\alpha_n)= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\alpha_n & -\sin\alpha_n & 0 \\ 0 & \sin\alpha_n & \cos\alpha_n & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \end{equation} であり、それぞれが各パラメータによる並進または回転の同次変換となっていることがわかります。 また、Modified Denavit–Hartenberg parametersというものもあり、上記の古典的なDHパラメータと比較して各座標系の原点と変換の順序が異なっています。 詳しくは Wikipediaの記事 などを参照してください。

順運動学

URのようなマニピュレータの順運動学を導出する場合、リンク0とジョイント0が乗っている座標系0からリンク6とジョイント6が乗っている座標系6への同次変換$T_6^0$を導出する必要があり、 $$T_6^0=T_1^0\cdot T_2^1\cdot T_3^2\cdot T_4^3\cdot T_5^4\cdot T_6^5$$ によって求められます。 $T_n^{n-1}$は$\alpha_{n-1}, a_{n-1}, \theta_n, d_n$を変数とする関数とみなせます。 そしてURの場合、$\theta_n$が独立の変数なので、実質的には$T_6^0$は$q=[ \theta_1, \cdots, \theta_6]$を変数とする関数となります。 $T_6^0=T(q)$とすると、順運動学は \begin{equation} \begin{bmatrix} r \\ 1 \end{bmatrix}=T(q)\begin{bmatrix} r_0 \\ 1 \end{bmatrix} \end{equation} から、最初に書いた$r=f(q)$を導けます。

逆運動学

順運動学から逆運動学$f^{-1}$を求めるためには、上の式から逆算で求めれば良さそうですが、$T_N^0$の$N$が大きくなるほど逆算は困難になります。 $N=6$にもなると、ほとんど無理です。 そのため、順運動学から数値解析的に求めるのがふつうです。 以下は姿勢$r_{tgt}$の時の関節変位$q_{tgt}$を求める手順です。
  1. $q=q_0$(初期値の設定)
  2. $r=f(q)$(順運動学で$r$を求める)
  3. $| r_{tgt} - r |$の大きさを調べる
    1. $| r_{tgt} - r |$が十分小さければ、$q_{tgt}=q$として終了する
    2. そうでなければ、順運動学のヤコビ行列の逆行列によって$q$を修正する。手順2に戻る。
ヤコビ行列とは、
一変数スカラー値関数における接線の傾きおよび一変数ベクトル値函数の勾配の、多変数ベクトル値関数に対する拡張、高次元化
です(Wikipediaより)。 つまり、勾配法の要領でヤコビ行列から$q$の修正すべき向きと量が決まって、$q_{tgt}$に近づけていけます。
$r=[r_1, \cdots, r_M], q=[q_1, \cdots, q_N]$の場合、順運動学は \begin{equation} x_i=f_i(q_1, \cdots, q_N) \end{equation} であり、ヤコビ行列の要素は \begin{equation} J_i(q_j)=\frac{\partial f_i(q_1, \cdots q_N)}{\partial q_j} \end{equation} と表せます。
姿勢の空間は$r=[x, y, z, r_x, r_y, r_z]$のため$M=6$となります。 また、URのような6DoFマニピュレータの場合だと$q=[\theta_1, ..., \theta_6]$のため$N=6$となります。 よってヤコビ行列は$6\times 6$の正方行列となります。

特異点

問題は、順運動学のヤコビ行列の逆行列が存在していない場合です。 逆行列を持たない正方行列の特徴として行列式が0(${\rm det} J=0$)となることが挙げられます。 ヤコビ行列の逆行列は \begin{equation} J^{-1}=\frac{\Delta_{ij}}{{\rm det} J} \end{equation} となるので、${\rm det} J$が0に近づくほど$J^{-1}$の要素の絶対値は大きくなります。 姿勢$r$と$J^{-1}$から関節変位$q$を求めるので、このときの関節変位の速度も急上昇し、結果的にロボットが暴走しているように見えます。 そして、${\rm det} J$が0となると、逆行列を算出できなくなり停止してしまいます。 これがロボット制御における特異点の問題です。

擬似逆行列

今日、様々な解決策が提案されています。 もっともよく知られているのは、逆行列の代わりに擬似逆行列を使う方法です。 擬似逆行列の利点は、上のような例における特異点を避けること、そして7DoFのような冗長ロボットのように$N\neq6$でないためにヤコビ行列が正方でない場合についても求められることです。 欠点は計算量が多いことで、スピードを重視して転置行列で近似してしまう方法もあります。

おわりに

エクサウィザーズは優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集していますので、ご興味を持たれた方はぜひご応募ください。
採用情報|株式会社エクサウィザーズ

注釈

1: ロボット(マニピュレータ)には直列タイプと並列タイプがあり、ここでは直列タイプについて扱う。直列タイプに含まれるのは、例えば UR, Panda, LBR iiwaなど、関節が直列な構造を持つものである。

2: $R_{OA}$は$3\times 3$の回転行列である。

エクサウィザーズ の技術力向上の取り組み

この記事について

皆さんご承知の通り、機械学習界隈は進化が早いです。一説によれば、機械学習に関する論文が1日100本以上出ているとも言われています。 そんな超速進化をしている機械学習ですが、それを扱うエクサウィザーズでは常に最新技術に追いつき、技術力を高めていく取り組みがあります。 この記事では、その取り組みの一部を紹介します。

社内における取り組み

社内では、主に2つの勉強会をしています。 案件共有会と論文読み会です

案件共有会

毎週1回1時間実施しており、主なトピックは取り組んだ案件の技術的/ビジネス的な取り組み内容の共有です。 この勉強会を通すことで、異分野との交流や知見の取り入れを諮り、相互作用による技術革新を狙っています。

この写真は最近行なった、ある自動車メーカーの異常検知タスク案件の取り組み共有の様子です。質疑応答も活発に行われました。 f:id:akira0926yosouguy:20191120151232p:plain

「ある分野では当たり前のアプローチが他の分野だとやられていない」というようなことが多々あります。特に弊社のようにケア事業、ロボット事業など取り組んでいる分野が多岐にわたる企業では、個々に取り組んでいると視野が狭くなったり、力が分散してしまいがちです。 このような知見の共有会を開くことで、各分野の技術交流を諮り、技術の転移・知見の共有で個々の技術を伸ばしていこうと考えています。

論文読み会

こちらも毎週1回1時間実施しており、論文1本当たり30分x2本という内容です。 毎週2人の担当者が質疑応答含め30分で、論文の内容をまとめて発表します。

1年間は約52週なので、この勉強会だけでも年間約100本分の論文の知見を取り入れることができます。 弊社では色々な分野の専門家がいるため、それぞれ異なったことに興味を持ち、選ぶ論文の研究分野もひとそれぞれです。普段自分が読まない分野の論文に触れることにより、技術の幅を広げることができます。

この資料は実際に発表で使われた資料です。弊社は海外籍の方も多いので、前半はこのように英語による発表をしています。

www.slideshare.net

そして、下記表は直近の発表内容ですが、ある分野に偏らずに色々なものが存在しているのがわかると思います。

論文のタイトル等 大まかな内容
RNNs Evolving on an Equilibrium Manifold:A Panacea for Vanishing and Exploding Gradients? RNNの改良
Neural Processes Gaussian Processのニューラルネットへの拡張
Gate Decorator: Global Filter Pruning Method for Accelerating Deep Convolutional Neural Networks ニューラルネットの枝刈り(圧縮)
Polygon RNN, Polygon RNN++ アノテーションを半自動化
Data Cleansing for Models Trained with SGD データクレンジングをNNを介して行う研究
Hamiltonian Graph Networks with ODE Integrator 物理シミュレーションへのDNN適用

社外を含めた取り組み

エクサウィザーズ では社内で閉じた取り組みだけでなく、社内の枠組みを超えた一般公開の勉強会も行なっています。 大きく分けると、研究者やエンジニア向けの国際会議や研究分野に絞った勉強会、キャリアやビジネス側の人も対象者含めた技術系以外の勉強会、の2つです。

近畿圏で多くの勉強会を行なっていることがエクサウィザーズ の特色です。 このような勉強会は首都圏では珍しくないのですが、近畿圏ではそこまで数は多くありません。 弊社は京都に拠点を持っているため、近畿圏で勉強会を開催することにより、近畿圏の機械学習コミュニティの醸成にも微力ながら貢献していきたいと考えています。

以前開催したCVPR2019読み会では、京都大学の鹿島先生もお招きして平日の19:30~21:00に3人の発表者x2日程で行いました。この資料は鹿島先生に登壇いただいた資料です。

www.slideshare.net

開催イベントはconnpassのExaWizardsグループのページから確認できますので、ご興味ある方は是非ご参加ください。 exawizards.connpass.com

国際会議や研究分野を絞った勉強会(研究者、エンジニア向け)

KDD, CVPR, AAAIのように注目度の高い国際会議の勉強会を開催しています。 たとえば去年行なったKDD 2018(データマイニング領域のトップカンファレンス)の論文読み会では、理化学研究所・京都大学と共同で行い、実際に参加された方を招待講演としてお呼びして開催しました。詳細や登壇資料は下記ブログをご覧ください。

techblog.exawizards.com

2019年の実績としては、CVPRの読み会, AAAIの読み会を実施しており、ICCVの読み会も実施予定ですのでご興味ある方は是非ご一緒に勉強しましょう!

exawizards.connpass.com

exawizards.connpass.com

また、GANやVAEなどの生成モデルにテーマを絞った勉強会も実施しています。

exawizards.connpass.com

ビジネス側の人も含めた勉強会やキャリアに関する勉強会など(技術系以外の勉強会)

世の中の課題を機械学習で解決することは、機械学習エンジニアが優れたモデルを作るだけでは達成できません。 その課題を機械学習の問題まで落とし込める「問題設定を考えるビジネス側の人」も巻き込む必要があります。 https://techblog.exawizards.com/entry/2018/08/15/184404エクサウィザーズでは、ビジネス側の方々も対象にした勉強会を実施しています。

exawizards.connpass.com

また、12月初旬にはマスクドアナライズさんを招いて、「これからの機械学習エンジニアに求められるスキル」をテーマに勉強会を行います。

exawizards.connpass.com

最後に

エクサウィザーズは機械学習の超速発展に対応するために様々な勉強会を開いて技術向上に取り組んでいます。 機会がありましたら、是非みなさんも参加してみてください

研究と両立しながら挑んだ3ヶ月間

1,はじめに

初めまして,3ヶ月間エクサウィザーズでお世話になりましたインターン生の井上です. 今回は研究と並行しながら臨んだインターンシップについて振り返り,エクサに興味を持っている方に取り組んだことや雰囲気を伝えることができれば幸いです.

自己紹介

早稲田大学の修士2年で機械学習に関するアルゴリズムや分析を行う研究室に所属し,現在は統計的因果推論の研究に携わっています. 学部では文系学部で統計学を学び,趣味の競馬に活用するためのAIの開発やデータ解析のコンペに参加していました. 現在は,機械学習のパッケージの使用経験や分析経験はあるものの,諸々の機械学習アルゴリズムについての知識は完全にわかっているというわけではない状態で不安と楽しみな感情を抱えつつインターンに臨みました.

インターンシップに参加するにあたって設定した課題

・インターンシップを通じて,どんなことに取り組みそこからどんな学びを得るのかというのを明確にするためにあらかじめ最終的な目標を設定しました. また,そこに到るために具体的にどのような進み方をするのかを検討しました.

【実際に設定した課題の例】

・機械学習に関する知識を広く身につける.そのために参考図書を読破する

・施策の立案に役に立つ手法の実装を行う

・実装した手法を用いて分析を行い,納得感の得られる施策を考える

などこのインターンシップ全体の大目標と共に短期的な中目標も設定した上で課題に取り組んでいきました.

インターンシップの初日に面接でお世話になった遠藤さんにお時間をいただき,ディスカッションを行いながら具体的な目標設定を行いました. 遠藤さんは私がインターンシップを通じた成果を感じられるよう,精力的にアドバイスやご指摘をしてくださり,目標設定にも非常に熱が入りました.

また,その後も目標がどの程度達成することができているのかを確認するために1 on 1で面談する機会を設けてくださり,お仕事がお忙しいにも関わらずよく目をかけてもらい,非常に感謝しています.本当にありがとうございました.

2,取り組んだこと

(1)機械学習周辺に関する勉強

機械学習周辺の知識を身につけるために課題の本を設定してもらい,約1ヶ月半で読破することを目標に取り組みました.

「[第2版]Python 機械学習プログラミング 達人データサイエンティストによる理論と実践」(表紙が緑の分厚い本に取り組みました)

最初から少しずつ読み進めていきましたが,読んではコードを写して実行しまたそれを繰り返す,という単純な作業を繰り返すことに飽きてしまったため,私はuci machine learning repositoryでサンプルデータを拾ってきて実際にデータを分析しながら,わからないところは本を参照しながら学ぶという形を取り勉強しました.また,理解したアルゴリズムはアウトプットして更に理解したいと思い,図を用いて端的にまとめるといった工夫をしながら進めることで楽しく勉強を進めることができました.

おかげで自分がこれまであまり触れたことの内容な手法の理解だけでなく,これまであやふやだった手法についても理解を促進することができたと感じました.

この期間は本の勉強に充てるだけではなく,実際に分析する際の手法の検討(主に論文の探索)も行い,見つけた手法が実際に適用することが可能かどうかを考える時間も設けていました.

(2)社内データを用いての機械学習モデルの構築

私は現在,統計的因果推論の研究をしているため可能であれば研究領域に近いことができると嬉しいなと思いながら機械学習手法の検討をしていました.

結果的に私はCare techのデータに対して因果探索手法を用いることができました.今後インターンシップを考えている学生の方へ”特に”伝えたいことは,

エクサウィザーズでは「対象とする手法が扱うデータに適合し,分析結果を通じて会社に利益をもたらすことが可能な機械学習モデルである」ということが伝えることができれば,インターンシップの立場であってもプロジェクトをデザインも主導することができるということです.

私自身は,自分がやりたいことをさせてくれた環境があるというのは非常に嬉しく感じました.

実際に取り組んだ手法は,

「Multiple-cause discovery combined with structure learning for high-dimensional discrete data and application to stock prediction」

https://link.springer.com/content/pdf/10.1007%2Fs00500-015-1764-8.pdf

という因果探索手法に着目しました.

f:id:K_Inoue_1030:20191024172829p:plain
論文中にある変数間の関係を模した図

この手法を用いることによって図のような因果関係を元にした変数間の関係を理解し,考察することを通じて納得間のある施策の立案につなげることができないかと考えこの手法に取り組みました.

【簡単なアルゴリズムの紹介】

Multiple-cause Discovery combined with Structure Learning(以下McDSL)では,大きく3つのステップに分かれたアルゴリズムになっています.


Step1: 変数間に何らかの因果関係があるかどうか探索する

Step2:不要な変数間の関係性を除去する

Step3:変数間の因果の向きを設定する


以上のような流れで変数間の因果関係を探索していきます.

Step1・2では条件付き独立性の検定を行い,変数間の関係性があるかどうかを確かめていきました.また,Step3では,統計的因果探索で用いられる回帰分析と独立性を考慮した方法によって因果の向きを定めていきました.(参照:清水昌平. 統計的因果探索. 講談社)

特に苦労したのは,条件付き独立性の検定を高次元データに対して適用する点でした.条件部に当たる変数が増大すると,非常に計算コストが増大してしまうため通常のカイ2乗検定による検定ではなく,以下の論文中にあるFCITという手法を採用しました.(https://arxiv.org/pdf/1804.02747)

実装を行った感想

実装自体に取り組み始めたのは8月の半ばからでしたが研究室の合宿や予稿の執筆もあり,かなりきつい時間でしたが濃密な時間だったように感じます.特に,うまく結果が出力されるまでに繰り返しアルゴリズムの理解を要し,それをプログラムとして具現化することや正しく結果を出せているかを確かめるためにシミュレーションを行うなどやることが多かったので日々必死に取り組みました.そのおかげで,何とか私がこれまでやってきたことを社内勉強会で共有し,インターンシップの最後を飾ることができたと思います.

実装自体は始めてみると楽しく,図が出力されうまく変数間の関係を表現した図が出力できたときには大きな達成感を感じることができ,良い経験になりました.また,社内の方々と図を元に結果の考察をした際に,図自体に興味を持っていただくことができたのでこうした点でも取り組んだ手法に意味があったのかなと感じています.

参考文献

・Chen, Weiqi, et al. "Multiple-cause discovery combined with structure learning for high-dimensional discrete data and application to stock prediction." Soft Computing 20.11 (2016): 4575-4588.

・Chalupka, Krzysztof, Pietro Perona, and Frederick Eberhardt. "Fast conditional independence test for vector variables with large sample sizes." arXiv preprint arXiv:1804.02747 (2018).

・清水昌平. 統計的因果探索. 講談社, 2017.

インターンシップの参考になれば・・・

・どのくらいの頻度で出社していたか?

→週2〜3日出社し,出社した際には10:00~19:00までフルタイムで勤務することが多かったのですが,都合に応じて自由にシフトを組むことができたので研究との両立をしながらインターンに参加し続けることができました.

・どんな人とお仕事をしたのか?

→私は,最終的にはCare techに関わるデータの分析を行うことになったのでCare techに関わってきたエンジニアの方と具体的な手法についてのディスカッションや実データに存在する変数に関しての議論を交わすことがありました.また,ビジネスサイドの方々とも関わることがあり,分析結果の考察や実際に結果を見せるにはどのようなデータを使うべきかといったことを熱心に話し合うことができました.協力してくださった皆さんのドメイン知識やこれまでの経験を通じたお話をしてくださったので勉強になることが非常に多かったです.私もなるべく自分の考えや分析結果を通じて思ったことを話したことに対して全力で向き合ってくれました.

・勉強会の内容や雰囲気は?

→勉強会ではこれまで取り扱った案件や参加した学会の雰囲気・学びが共有されることが多かったです.私はこの勉強会を通じてエクサの関わっているお仕事について多く知ることができたと思います.個々の勉強会の内容も非常に興味深いものが多く,聞いたことのある手法が実際に現場ではどのように使われるのかといったことを知ることができると思います.もし,エンジニアインターンを希望する学生の皆さんは積極的に参加することをお勧めします!!

3,最後に

3ヶ月間(特に最後の1ヶ月)はアルゴリズムの実装と予稿の執筆に追われ,アイデアが思いついた拍子に夜中に起きる日が続くなど大変なこともありました.しかし,機械学習の基礎の勉強から実装さらには実データの分析を行うことを通じて大幅に短期間でレベルアップができました.自分で取り組む課題を決めて,周囲の人を巻き込みながら仕事を進めていくというフローを実際に体験できたことは今後の大きな糧になると感じています.このような場を用意してくださったエクサウィザーズの皆様には本当に感謝しています.

3ヶ月間本当にありがとうございました.

尚、エクサウィザーズは優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集しています。ご興味を持たれた方はぜひご応募ください。 採用情報 - 株式会社エクサウィザーズ

ExaWizards Engineer Blogでは、定期的にAIなどの技術情報を発信していきます。Twitter (https://twitter.com/BlogExawizards) で更新情報を配信していきますので、ぜひフォローをよろしくお願いします!

論文がネイチャーの姉妹誌「Nature Protocols」に掲載されました

こんにちは、エクサウィザーズの遠藤太一郎です。

私が参加した研究プロジェクトの成果が英科学誌「Nature Protocols」に掲載されましたので、ご報告です。 細胞を画像解析し、自動で分類する仕組みの再現方法などを、詳細に記述しています。 前回のCell掲載に引き続き、画像解析の深層学習のところで貢献しました。

論文は以下のURLから確認可能です。

https://www.nature.com/articles/s41596-019-0183-1

f:id:taichiroendo:20190708162740p:plain 本論文より引用

エクサウィザーズでは各種大学や研究機関と、共同研究を始めとし様々な連携を行っています。技術顧問の先生方とのディスカッションを始め、京都大学・理研AIPとの機械学習勉強会など、共催のイベントなども積極的に開催しています。

優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集していますので、ご興味を持たれた方はぜひご応募ください。 採用情報|株式会社エクサウィザーズ

ExaWizards Engineer Blogでは、定期的にAIなどの技術情報を発信していきます。Twitter (https://twitter.com/BlogExawizards) で更新情報を配信していきますので、ぜひフォローをよろしくお願いします!

ディープラーニング初心者の僕がエクサウィザーズで6週間インターンして圧倒的成長した話

はじめに

はじめまして。エクサウィザーズでインターン生としてお世話になりました中野と申します。
このブログを通して、エクサウィザーズでのインターンの雰囲気やどんなことが学べるのかが伝わればと思います。

自己紹介

京都大学の修士一年生で、機械の制御について研究しています。
フィリピン旅行で力こそ正義だと気づき、最近ボクシングをはじめました。
インターン開始時、ディープラーニングを除く機械学習の経験は多少あったものの、ディープラーニング実装の経験はほとんどありませんでした。

やったこと①

概要

この、DonkeyCarというメカメカしいラジコンの自動運転に挑戦しました。
香港から輸入することで購入できます。日本円にしてだいたい35000円だそうです。

f:id:sonias:20190205135137p:plain

余談ですが、ドンキーというと某ゴリラを想像したのですが、ロバという意味らしいです。

組み立て

f:id:sonias:20190205151021p:plain

f:id:sonias:20190205151019p:plain

プラモデルの組み立てのようで楽しかったです。
ハンダ付けなどは不要でした
配線の解説ページが見つからず苦労しましたが、脳死して総当たりすることで無事通電させることができました。 その他にも、公式サイトが不親切なためデフォルトでないログインパスワードがわからないなど、ハマることが多々ありましたが、メンターの小野さんに相談し、何度も助けていただきました。

学習

教師データとして、DonkeyCar視点の画像を入力とし、その時のスロットルとタイヤの角度を出力としたデータを用い、DonkeyCar視点の画像からスロットルとタイヤの角度を算出するモデルを作成しました。 ネットワークはNVIDIAのPilotNetを参考に作成しました。 DonkeyCarにはシミュレーションソフトが存在するため、シミュレーション上でのデータでモデルを作成し、その後現実のデータで転移学習し、実機で自動運転を行う、という方針で学習を進めました。 以下、今回使用したネットワーク図です。

f:id:sonias:20190205173600p:plain

シミュレーション

教師データ作成

シミュレーションでの教師データは、道路の中心線に追従するPID制御で取得します。 PID制御の神パラメータを探し当て、教師データを作成しました。

自動運転

シミュレーション上のランダムに生成されたデータのみで学習したモデルで走行している様子が以下になります。 カーブなどにも対応しているのが見て取れます。

f:id:sonias:20190206122819g:plain

実運転

教師データ作成

転移学習のための実機で教師データを取得しました。 データ取得の際の操作はPS4コントローラーで行いました。データに関しては先程と同様に、カメラが取得した画像とその時のスロットルとタイヤの角度が紐ついて保存されます。 余計なデータが入らぬよう頑張るうちに、操作が熟練しました。

f:id:sonias:20190226150024p:plain

1本線上を走行

追従していることが見て取れます!!

2本線の間を走行

先程より難しいのか、最後にコースアウトしていますが、追従している様子が見て取れます!

考察・展望

  • シミュレーションではタイヤの角度を急に変化できるが、実機だと連続的にしか変化できないなどといった、実機とシミュレーションの違いを転移学習でうまく調整できました。
  • 2本線の場合だとコースアウトしたときのデータセットが必要そう。(1本線だとコースアウトが存在しないため)
  • RasberryPiの計算能力上げて画像処理を挟んだり、処理を複雑化してみたいです。

大変だったこと

マニュアル通りの環境だとプログラムが動かず、環境構築が大変でした。
メンターの小野さんに相談しまくることでなんとか解決しました。

やったこと②

概要

Dueling DQNという深層強化学習を用いた自動運転をシミュレーション上で実装して、挙動を検証しました。

学習

学習風景です。 報酬を、道路の中心ラインに近いほど大きく設定し、入力をDonkeyCar視点の画像に対して、タイヤの角度を学習しました。

f:id:sonias:20190205154512g:plain

以下、ネットワーク図になります。 f:id:sonias:20190205180539p:plain

結果

スムーズではありませんが、コースを示すラインに反応し動いています。

f:id:sonias:20190205174411g:plain

考察・展望

  • 道路の中心方向にタイヤの角度を向けても、短期的に見れば中心方向から離れていくことが起きているので、それを考慮できるアルゴリズムを適応すればどうなるか検証してみたいです。

タイムスケジュール

参考にですが、どのようなタイムスケジュールでおこなったかを記しておきます。
ほとんど進捗の無い週がありますが、サボっていたわけではなく、それだけ自由にシフトを組ませていただいたということですので、あしからず。

1週目

  • ディープラーニングの学習
  • ディープラーニングのネットワークの論文読み
  • WideResNetやLTSMをPytorchで実装

2週目

  • DonkeyCar組み立て

3週目

  • 走行コース作成
  • 走行モデル学習
  • RaspberryPi環境構築

4週目

  • 強化学習の学習
  • RaspberryPi環境構築

5週目

  • 強化学習実装
  • 実機データ収集

6週目以降

  • 実機自動運転

環境

内装

きれいで過ごしやすかったです。
おやつ、バリスタ使い放題でだったため、たくさん利用させていただきました。
バリスタで作るコーヒー美味しかったです。 f:id:sonias:20190205134641p:plain

就活相談

リクルート出身の半田さんが就活相談に乗ってくださりました。
就活を深く考えず進めようとしていた僕でしたが、半田さんへの相談により、軸や着眼点が明確になり、時間が無い中で就活を効率的に進める方法を理解しました。
また、僕の要望に応じて、外資金融や最大手SIer出身の社員の方とのミーティングを設定していただき、その点においてもキャリアを考えることにおいて大変参考になりました。

プログラミング環境

  • MacBookProメモリ16GB付与+社内GPU使い放題でした。
  • 無限に書籍買ってもらえました。
  • インターン生のためsudo権限が無いことで環境設定で少し詰まりました。

通勤・待遇

京都大学から徒歩1分。
シフトが柔軟に組めて、インターンが研究会やテストの阻害になることも一切ありませんでした。
給料をいただきながら勉強させてもらえるので、プログラミングに抵抗ない人はとりあえずインターン応募すべきだと思いました。夜勤で命削っていたころよりも給料が高くて衝撃でした。
もっと早く知りたかったなぁという気持ちがあります。 東京の学生は機会に恵まれていて羨ましい。。

最後に

2ヶ月という限られた時間でしたが、得られるのもが大きく濃密なインターンとなりました。
メンターの小野さんが実践と理論をいい感じに組み合わせてわかりやすく教えてくださり、ディープラーニングを学ぶ最短ルートを歩めたように思います。 そのおかげで、ディープラーニング初心者は脱することができたように感じます。
社員の皆さん、メンターの小野さん、2ヶ月間ありがとうございました。

画像の内容をAIが文章で答えるデモ

f:id:kentaro-suto:20190124195850j:plain

こんにちは。エクサウィザーズAIエンジニアの須藤です。

エクサウィザーズ が提供しているAIプラットフォームexaBaseに、「画像の内容をAIが答える」という事例があります。 画像解析とテキスト生成という、ディープラーニングでも特に成功している分野の組み合わせであり、いかにも人工知能らしい応用例となっています。

今回、これをWebブラウザ環境に移植できたので報告します。 いつもよりモデルが大規模なため動作環境が限られるのですが、特別な設定などは必要ありませんので、気軽に試していただきたいと思います。

作り方

このアプリケーションは、画像解析を担当する学習済みInceptionモデル*1と、テキスト生成を担当するLSTMモデルの2つで構成されています。 処理の流れは以下の通りです。

  1. 必要なモデルを読み込む。
  2. 画像を取得する。
  3. 画像をデータに変換する。
  4. 画像データをInceptionモデルに与え、特徴量を得る。
  5. LSTMモデルに、特徴量と開始コードを与え、次の単語の確率を推論する。
  6. 最も確率の大きい単語を選び、画面に書き出す。
  7. LSTMモデルに、特徴量と選んだ単語の番号を与え、次の単語の確率を推論する。
  8. 終端コードが選ばれるまで4と5を繰り返す。

元のコードはPython + Kerasで書かれていました。 これをJavaScript + Tensorflow.jsに書き直します。 読み込みや推論など、元々フレームワークを使用していた部分は、JavaScriptでも同等の機能で置き換えることができます。 その他のPythonで直接記述されていた部分は、JavaScriptに翻訳する必要があります。

また、オリジナルのモデルでMergeレイヤーが使われていましたが、これはTensorflow.jsがまだ扱えないクラスです。 Concatenateレイヤーを使ってモデルを書き直す必要がありました。

動作環境

モデルの規模が大きくメモリを大量に消費するためか、動作できる環境が限られます。 参考までに私の環境での検証結果を示します。 ハード環境によっては異なる結果になるかもしれません。

プラットフォーム ブラウザ バージョン 対応状況
macOS Safari 12 × 実行途中で再読み込み
macOS Chrome 71
macOS Firefox 64
macOS Opera 57 × 読み込みでエラー
Windows IE 11 × JavaScriptが未対応
Windows Edge 42 x 読み込み中に再読み込み
Windows Chrome 71 × 読み込みでエラー
Windows Firefox 64
Windows Opera 58 × 読み込みでエラー

使い方

  1. このページにアクセスしてください。 https://base.exawizards.com/view/modelDetail?id=41

  2. ページの中ほどのリンクをクリックして、しばらくお待ちください。 f:id:kentaro-suto:20190124182906p:plain

  3. 2つのモデルを別々に読み込んでいます。このように表示されたら折り返し地点です。 f:id:kentaro-suto:20190124185412p:plain

  4. UIが表示されたら、サンプル画像を選択するか、ローカルファイルを読み込ませてください。 f:id:kentaro-suto:20190124185754p:plain

5.画像を説明するテキストが表示されます。 f:id:kentaro-suto:20190124185923p:plain

結果の例

手持ちの画像で検証しました。

画像 テキスト ひとこと
f:id:kentaro-suto:20190124190550j:plain two white and white cat standing on top on the roof 白茶でなくて白白なのが惜しいですが、ほぼ合っています。
f:id:kentaro-suto:20190125133238j:plain cows are standing on the grass near the grass たまに同じ言葉を繰り返します。
f:id:kentaro-suto:20190124191659j:plain the snow covered street is covered with snow 雪が積もりまくっていますね。
f:id:kentaro-suto:20190124192218j:plain the cake is on the plate with the other fruit ばななが入ったお菓子、正解です。
f:id:kentaro-suto:20190124190820j:plain an open box with some food on it 国籍も不明だし、なるほどなんらかの食べ物としか言えませんね。
f:id:kentaro-suto:20190124192613j:plain there is some food that is on the table とにかく食べ物なことはわかるようです。
f:id:kentaro-suto:20190124192917j:plain the yellow flower is growing on the side オレンジの花が嫌いなんでしょうか。
f:id:kentaro-suto:20190124193151j:plain cars parked on the side walk near trees うまくいっている例です。
f:id:kentaro-suto:20190124193727j:plain the seagull is standing on the boardwalk near the stairs 階段も遊歩道も実は近くにあります。「ありそうな雰囲気」で判断しているのかもしれません。
f:id:kentaro-suto:20190124193331j:plain an image shows an image on the page to describe 説明できていない感じが伝わります。

まとめ

ブラウザ上で動く、画像の内容をAIが答えるデモを作りました。

尚、エクサウィザーズは優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集しています。ご興味を持たれた方はぜひご応募ください。 採用情報|株式会社エクサウィザーズ

ExaWizards Engineer Blogでは、定期的にAIなどの技術情報を発信していきます。Twitter (https://twitter.com/BlogExawizards) で更新情報を配信していきますので、ぜひフォローをよろしくお願いします!

*1:Inceptionモデルの重みは Apacheライセンスの下で公開されています

ブラウザで動く落書き判定モデルの作り方

はじめに

こんにちは。エクサウィザーズAIエンジニアの須藤です。

昨年の弊社忘年会の出し物として、落書き判定モデルを作りました。 お題に合わせて絵を書いて、AIにそれと判定させたら勝ちになるゲームです。 思いのほかちゃんと判定してくれて、ほっとしました。 取り立てて目新しさはありませんが、皆さんにも遊んでいただきたいと思い、ここで紹介します。

exaBaseのモデル詳細ページで実際に遊べます。 ブラウザだけで動作しますので、お気軽にお試しください。

データセット

Googleが提供しているQuick, Draw!というゲームのデータを使用します。 これは、お題に合う絵を描いて、AIに判定してもらうというゲームです。 制限時間は20秒で、AIが候補に挙げた時点でクリアとなります。 世界中のプレーヤーによって描かれた絵が、学習用データベースとして無償で提供されています

データセットには

  • ストローク
  • ストロークを画像(28x28x1)にしたもの
  • カテゴリー
  • 国情報
  • 時刻情報

などが含まれています。今回は画像とカテゴリーだけを用いて学習を行います。 ストロークを利用する学習モデルについては、以前の川畑さんの記事をご覧ください。

画像データはカテゴリー別にNumPy形式のバイナリファイルになっていて、Pythonで

np.load('cat.npy', mmap_mode='r')

とすると読み込むことができます。 1500万人が遊んだというだけあって、約5千万サンプル、約40GBの巨大なデータです。

カテゴリーは以下の通りで、全部で347あります。

エッフェル塔 万里の長城 モナリザ 空母 飛行機 目覚まし時計 救急車 天使 動物の移動 蟻 金床 りんご 腕 アスパラガス 斧 バックパック バナナ 包帯 納屋 バット 野球 バスケット バスケットボール コウモリ バスタブ ビーチ くま あごひげ ベッド 蜂 ベルト ベンチ 自転車 双眼鏡 鳥 誕生日ケーキ ブラックベリー ブルーベリー 本 ブーメラン ボトルキャップ 蝶ネクタイ ブレスレット 脳 パン 橋 ブロッコリー ほうき バケツ ブルドーザー バス ブッシュ 蝶 サボテン ケーキ 電卓 カレンダー ラクダ カメラ 迷彩 キャンプファイヤー ろうそく 大砲 カヌー 車 人参 城 ネコ 天井ファン 携帯電話 チェロ 椅子 シャンデリア 教会 サークル クラリネット 時計 雲 コーヒーカップ コンパス コンピューター クッキー 冷却装置 ソファー 牛 カニ クレヨン クロコダイル 王冠 遊覧船 カップ ダイヤモンド 食器洗い機 飛び込み台 犬 イルカ ドーナツ ドア ドラゴン 化粧ダンス ドリル ドラム アヒル ダンベル 耳 肘 象 封筒 消しゴム 眼 めがね 面 扇風機 羽 柵 指 消火栓 暖炉 消防車 魚 フラミンゴ 懐中電灯 ビーチサンダル フロアランプ 花 空飛ぶ円盤 足 フォーク カエル フライパン 庭用ホース 庭 キリン あごひげ ゴルフクラブ ぶどう 草 ギター ハンバーガー ハンマー 手 ハープ 帽子 ヘッドホン ハリネズミ ヘリコプター ヘルメット 六角形 ホッケーパック ホッケースティック 馬 病院 熱気球 ホットドッグ 温水浴槽 砂時計 観葉植物 家 ハリケーン アイスクリーム ジャケット 刑務所 カンガルー 鍵 キーボード 膝 ナイフ はしご ランタン ノートパソコン 葉 脚 電球 ライター 灯台 稲妻 線 ライオン 口紅 ロブスター ロリポップ メールボックス 地図 マーカー マッチ メガホン マーメイド マイクロフォン 電子レンジ 猿 月 蚊 バイク 山 マウス 口ひげ 口 マグカップ キノコ 爪 ネックレス 鼻 海洋 八角形 たこ 玉ねぎ オーブン ふくろう ペンキ缶 絵筆 ヤシの木 パンダ ズボン ペーパークリップ パラシュート オウム パスポート 落花生 梨 豆 鉛筆 ペンギン ピアノ ピックアップトラック 額縁 豚 枕 パイナップル ピザ ペンチ 警察車 池 プール アイスキャンデー はがき じゃがいも コンセント 財布 ウサギ アライグマ 無線 雨 虹 レーキ リモコン サイ ライフル 川 ジェットコースター ローラースケート ヨット サンドイッチ のこぎり サックス スクールバス はさみ サソリ ドライバー ウミガメ シーソー 鮫 羊 靴 ショーツ シャベル シンク スケートボード 頭蓋骨 超高層ビル 寝袋 笑顔 かたつむり ヘビ スノーケル スノーフレーク 雪だるま サッカーボール 靴下 快速艇 クモ スプーン スプレッドシート 四角 殴り書き リス 階段 星 ステーキ ステレオ 聴診器 縫い目 一時停止標識 コンロ イチゴ 街路灯 サヤインゲン 潜水艦 スーツケース 太陽 白鳥 セーター スイングセット 剣 注射器 Tシャツ テーブル ティーポット テディベア 電話 テレビ テニスラケット テント 虎 トースター つま先 トイレ 歯 歯ブラシ 歯磨き粉 竜巻 トラクター 信号機 列車 木 三角形 トロンボーン トラック トランペット 傘 下着 バン 花瓶 バイオリン 洗濯機 スイカ ウォータースライダー 鯨 ホイール 風車 ワインボトル ワイングラス 腕時計 ヨガ シマウマ ジグザグ

画像を可視化してみると、かなり雑で記号的な絵になっていることがわかります。

f:id:kentaro-suto:20190110180140j:plain f:id:kentaro-suto:20190110180208j:plain f:id:kentaro-suto:20190110180218j:plain f:id:kentaro-suto:20190121170519j:plain f:id:kentaro-suto:20190121170607j:plain f:id:kentaro-suto:20190121170631j:plain f:id:kentaro-suto:20190121170716j:plain f:id:kentaro-suto:20190121170745j:plain f:id:kentaro-suto:20190121170815j:plain f:id:kentaro-suto:20190121170851j:plain

モデル

畳み込みと全結合による、ごくシンプルなモデルです。 Python+Kerasで実装しました。

model = Sequential()
model.add(Reshape((28,28,1), input_shape=(784,)))
model.add(Conv2D(64, 5, padding='same')) #畳み込み
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(64, 5, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D())
model.add(Conv2D(128, 5, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(128, 5, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D())
model.add(Conv2D(128, 5, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(128, 5, padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Flatten()) #ここから全結合
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(345, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

学習

データセットからランダムにサンプルを選んで、入力(画像データ)から出力(カテゴリーごとの確率)が得られるように、学習を行います。

学習量は

  • バッチサイズ=100
  • ステップ数=40000
  • エポック数=100
  • のべ=4億サンプル

でした。

インターフェイスと使い方

使い方を、実装詳細とともに解説します。 インターフェイスはHTML+JavaScript+Tensorflow.jsで作成しました。 Tensorflow.jsの基本的な使い方については以前の記事をご参照ください。

1.ページを開く

このページにアクセスします。 ページを開くとすぐに読み込みが始まります。 ダウンロードデータは全部で8.4MBあります。ネットワーク環境によってはお時間をいただくかもしれません。

2.絵を描く

ページ全体がキャンバスになっています。 ドラッグで線を描いてください。 f:id:kentaro-suto:20190111194202p:plain

判定時には線が描かれた領域だけがモデルに合わせてリサイズされるので、どこにどんな大きさで描いても大丈夫です。 間違えたら「リセット」で全消去できます。

リサイズで線の太さがバラつかないように、線を描画するとき、同時にストロークデータとしても保存しています。

3.判定させる

「送信」ボタンを押すと判定処理を開始します。

保存したストロークデータを用いて28×28の領域に再描画をします*1。 描いたピクセルを配列に変換し*2、モデルに入力します。

4.結果を見る

判定結果を表示します。

f:id:kentaro-suto:20190111195534p:plain

モデルの出力は各カテゴリーの確率として得られます。 その中で、最も大きなものに対応するカテゴリー名を表示します。 他のカテゴリーの確率は、詳細をクリックすると見られるテーブルに書き出します。

実行例

f:id:kentaro-suto:20190111200253p:plain f:id:kentaro-suto:20190111200309p:plain f:id:kentaro-suto:20190111200346p:plain f:id:kentaro-suto:20190115103611p:plain
これはドアで、 これが枕です。 四角と判定させるには、場違いな正確さが要求されます。 円については、そこまでシビアではありません。
f:id:kentaro-suto:20190111200204p:plain f:id:kentaro-suto:20190115103907p:plain f:id:kentaro-suto:20190111203526p:plain f:id:kentaro-suto:20190115101151p:plain
うっかりネコにしましまを描くと、高確率で虎になります。 学習データ全部、殴り書きのようなものなので、 リアルさにこだわると、却って判別されないことがあります。 極限まで図案化するのがいいようです。
f:id:kentaro-suto:20190115143611p:plain f:id:kentaro-suto:20190111202410p:plain f:id:kentaro-suto:20190115143713p:plain f:id:kentaro-suto:20190111201550p:plain
よくわからないなにかを描いても 必ず、347カテゴリーのどれかに判定します。 難しそうなカテゴリーも 意外に簡単な特徴で判定している場合があります。

まとめ

落書き判定モデルを作りました。 花とか月といった、誰でも同じようになる絵は高い精度で認識します。 期待通りに認識しない場合もありますが、間違い方に妙な納得感があったりします。 機械学習の面白くて不思議なところです。

尚、エクサウィザーズは優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集しています。ご興味を持たれた方はぜひご応募ください。 採用情報|株式会社エクサウィザーズ

ExaWizards Engineer Blogでは、定期的にAIなどの技術情報を発信していきます。Twitter (https://twitter.com/BlogExawizards) で更新情報を配信していきますので、ぜひフォローをよろしくお願いします!

*1:このとき学習データに合わせて線の太さを1.5ピクセルにするのが重要です。 1ピクセルではまともに判定しません。 この対策を思いつくまでに大分手こずりました。

*2:このとき背景が0になるように、明るさの反転も行います。