マルチモーダルなDNNを扱うサービスの本番環境でやらかした話

こんにちは!ころんです。

ちょっと長い間更新をさぼっていましたが、元気にやってます!

よく見たら去年のADTも書いてなかったですね。今年は17日目になります。

adventar.org

 

TL;DR

  • Concatレイヤーの順番が設計したモデルと同じか確認しよう
  • モデルをデプロイする前に精度指標以外にもモデルの分布を確認しよう
  • 学習時とServingで同じ特徴量をいれたら同じ出力になるか確認しよう

DNNモデル

現在とあるサービスの機械学習モデリングとその運用の仕事に携わっています。

(詳細はお話できなくて申し訳ないです)

 

機械学習と言っても様々なドメインがありますが、画像とテーブルデータを用いたDNNを作成しています。いわゆるマルチモーダルですね。

 

モデルの構造としては画像の畳み込みレイヤーテーブルデータの特徴の全結合層をそれぞれn次元にまで圧縮、Concatした特徴量を全結合層に通してスカラー値を出すようなモデルです。下記はイメージ図です。

 

f:id:Collonville:20201217185853j:plain

 

一般的なマルチモーダルモデルのアーキテクチャになっており、学習したモデルをk8sでマネージドしているサーバーにServingし運用しています。

 

また学習時と推論時では参照しているリポジトリや環境も違うため※1、それぞれが独立して動作するような構成になっています。

 

※1 学習はGCPのAI Platform、推論時はk8sでtewnsorflowのバージョンは合わせて運用しています

何が起こったか

上記で作成しているモデルは特注なロス関数を組み込んでいるため、学習が終わったらモデルの重みを保存し、Serving時はその重みを読み込んだ上で学習時に使ったモデル構造を再度記述した上で実行しています。

 

そしてモデルを本番環境にリリースして数日後、社内からモデルが出している値がほとんど変化しないという報告をもらいました。

 

原因

通常tensorflowでモデルを保存するときは、モデル構造と重みを同時に保存するsaved modelh5形式が使われます。

しかしながら、今回は重みだけを保存する形式のためサーバーには学習時に使ったコードをコピーして記述する必要がりました。

 

ここでミスをやってしまいます。

 

アーキテクチャに戻りますが、Concatする際はTable data + Imageの順番でベクトルの結合をしています。

しかし、サーバー側ではImage + Table dataで結合してしたのが原因で、本来計算される重みが適切にかけられていない事象が発生していました。

f:id:Collonville:20201217185853j:plain

コードで表すとこんな感じ。

 

原因が発覚しすぐに修正PRを出しましたが、裏では様々なバッチが動いており復旧には数日かかりました。

 

解決策

上記の事象をチームで共有後に解決策を練りました。

 

1. レビューの強化

PRでサーバーのモデル構造に変更を加える際は、元となる学習のコードもセット(githubのurlで十分)にしてレビューをするように意識付けをしています。

チームでは複数のMLエンジニアがモデルを作成しているので、それぞれのモデルにメインの担当者を付けてダブルチェックする体制も入れました。

2. 検算の仕組みを作る

学習したモデルとサーバーから返される値に違いがないかをチェックする仕組みを作る。これをするとサーバーに実装した前処理にもミスがないか確認できるのでCI/CDに組み込んで自動的に検出できるようにします。

 

噂ですがTensorflow Pipelineにはそういう機能があるらしい?

3. データの可視化

実は本番環境へデプロイする前に、testに使った真値と予測値との分布の乖離を確認するために可視化した結果をSlackに通知する機能がありました。

今回はたまたまconcatを逆にしても大きな乖離が出なかったため見落としていました。しかし、よく見ると以前学習したモデルに比べてピークになっている値が多くあったため、傾向として捉えることができたはずでした。

 

そもそも可視化をしていなかれば気づけなかったことが多くあります。単純にモデルのRMSEといったロス指標だけではなく、必要箇所でデータの可視化を行うことが改めて大切であるということが学べた機会でした。

 

まとめ

今回はDNNのConcatレイヤーでやらかして本番にデプロイしちゃった話を書かせていただきました。問題発覚時は入社して一番冷や汗書いたので、ML系のサービスを運用する際には気をつけましょう。

 

明日のTUT Advent Calender 18日目はあやふみさんです!

まだタイトルも決まってないようですが、 どうなるんでしょう👀

TUT内で新規サービス開発を始めたお話

こんにちわぁぁああ!!!!こんばんわあああ!!!!ころんでぇぇす!!!

なにこれ?

これはTUT Advent Calendar 2018  15日目の記事とCyberAgent 19新卒 エンジニア Advent Calendar 17日目(早く出してごめんなさい!)の記事です

 

豊橋技術科学大学 & 東京工科大学合同のアドベントカレンダーであり、CyberAgent 19新卒エンジニアのアドベントカレンダーという一大イベント。

 

SAPPORO CHU-HI 99.99を飲みながら書かせていただきます。

(クリア グレープフルーツおいしいね)

 

カラオケは好きですか?

自分の場合、なぜか好きな時と嫌いな時がありますが今は好き!

懐かしのボカロ曲やアニソンを聞くと行きたくなる時期です。

 

そんな中、ちょっとした問題が自分にはあります。

 

 

それは、出せる音域が非常に狭いこと

 

 

なので、大体の曲は原キーでは歌えないのでキーの変更を余儀なくされます。

Aメロは歌えるけどサビは無理。部分的にはいけるみたいなのが多いので自分に合うキーを探索、記録には苦労します。

 

アンケートにご協力いただいた方は見たことがあると思いますが、キー変更をよくする人が12.3%もいてちょっと安心しました。

こちらでやってます-->カラオケに関するアンケート

f:id:Collonville:20181216013322j:plain

歌う曲のキーを変更しますか?に対するアンケート結果

意地でも原キーな人も割といるんだなと実感

 

記録は以下のようにiPhoneのメモ機能を用いています(一部をスクショ)

f:id:Collonville:20181215224623p:plain

 

じゃ、記録できるアプリがないのかと言われたら一応あります。

あるけどアプリの完成度としては自分は満足していません。

 

不満点でいえばこのような感じ

 

  • そもそも落ちる。特定の動作で固まる
  • UIが不便。とる大きさと得られる情報量が一致しない
  • 音程解析がただのフーリエ変換の測定結果
  • アプリの世界観が伝わらない

 

落ちるアプリはそもそも論外です。それも某大手のアプリですが。

UIと世界観ですが、個々のパーツをそのまま置いただけのような昔の業務用アプリが多いです。

最近のAWA、Tictok、Spotifyもそうですがアプリ1つ1つに世界観があると思っています。アプリを使用しているときの安心感があります。

音域解析ですが、これは本当にただのフーリエ変換で最大ピークをもつ周波数帯をグラフ化したものです。当然それで出せる音域は測定できますが、それが本当に気持ちよく歌える音域ですか?と言われたら違うはずです。
統計的、アカデミックな視点から解析できると思っています

 

このように(継続して)使ってみようと思うアプリが自分の中ではありませんでした。

 

無ければ作ればいいじゃない!!

自分のモットーでもあります「無ければ作ればいいじゃない!

ようは自分の満足するアプリがなければ作ってしまおうという、考えです。

 

TUT内でサービス開発やってる話聞かないし、作っちゃえ!!

 

作りたいアプリを説明したうえで、同じTUT内の友達や後輩を巻き込んで一緒にアプリを作ることになりました。

 

サービス内容

残念ながら今回の記事ではまだ公開できません。

音楽関係であるため著作権に引っかかるなどの制限がありますが、それ以外でできる部分で勝負かけます

 

f:id:Collonville:20181215234615j:plain

アプリの設計案

 

技術的内容

アプリ開発はスピードが大切だと思います。今できる最善の手で使えるツールがあるのなら積極的に取り入れるべきだと考えました。

 

AWS Mobile Hub(モバイルアプリケーションの構築、テスト、モニタリング)| AWS

 

AWS Mobileはユーザー認証を行うAWS Cognito、そのほかAPI gateway, Lamda, S3, DynamoDBなどモバイル開発におけるハブ機能を果たします。

各サービスで無料枠が使えるので

  • 開発やリリース初期でも費用の問題がない
  • サーバー構築に時間を取られない
  • 開発メンバーがパブリッククラウドに触れられるいい機会
と思い選定しました。
 
また開発メンバーが初学者であるため自分もiOSの勉強をする必要があります。
しかし、小さい時からwindowsっ子で育ったためmacは持っていません。
 
たまたまチーム発足時にmac miniの発売が発表されたため、ローンを組んでポチりましたw

 

f:id:Collonville:20181216001432j:plain

mac miniをぽちった

グラフィック以外はおおむね満足してます。到着が楽しみです。

 

あと基本チームの連絡はSlackで行い、タスク管理はtrelloで行うことにしました。

使い慣れた & 連携がスムーズにいくという点で決定。

 

進捗

現在の進捗ですが、コンセプト、アプリの基本機能、アイコンデザイン、サービス名、技術選定の案だしは終わりました。
ただ卒業研究と論文提出の月であるため、本格的に始動するのはクリスマス後になります。

 

目指すチーム像

ここからは自分がチーム開発するうえで大事にしていることの一部を書きます。

  • いい意味でフラットな関係を作る
     後輩、同年、先輩間で「年上だから意見を言うのやめよう」とか「自分より技術低くそうだからこの情報共有しなくていいっか」など勝手な価値観で情報共有をしないのはものすごいもったいないことだと思います。
     「グループ」ではなく「チーム」なのだから共通の目的、達成すべき目標、アプローチ方法はチーム全員が共有されているべきです。
     そのためにも、リーダーである自分からまず情報開示を行に信頼を得るように意識しました。
    Gitの使い方、APIの共有、調査報告、etc...ググれば分かるかな?と思う内容も共有します。共有内容+コメント(例:これここで使えそうじゃね?)があればよりgood.
    この内容に関してはチームの技量にもよりますが、今回はチーム開発未経験者を含めて考えています。
     情報共有とフィードバックを繰り返すことで共有することの大切さが実感でき、少しづつの成果が自信へと繋がり信頼につながると思っています。

  • HRT(謙虚・尊敬・信頼)を持つ
     謙虚(Humility)、尊敬(Respect)、信頼(Trust)の頭文字をとった言葉です。これはオライリーの「Team Geek」で書かれている、当時のGoogleのチームリーダーが優れたチームを作り上げるときに工夫したものに書かれています。
     1つ1つ語ると長くなりますが、要約すると

         自分は常に間違っているという可能性を考え
         相手に対する尊敬の気持ちを持ち、
         信頼関係を育もう

     ということです。詳しくはお酒飲みながらお話ししましょうw


まだまだありますが、このような思考を教えてくれたおすすめ書籍を紹介して終わりにします。

 
卒業するまであと3か月ちょいでリリースまでもっていけたらと思うのでよろしくお願いします!

明日(いや、実質今日)は、katura46さんですが何を書くのが気になりますね!乞うご期待!!

 

 

 

 

 

GTX760のWin10にKerasを導入したのでメモ

ディープラーニングってやつでなんとかして!!!!

ってことで今の環境にニューラルネットワークライブラリであるKerasを導入したのでメモ

ちょっとしたバージョンの違いだけでも動かないので注意してください。

 

CUDA 9.0 の導入

NVIDIAから出してる並列処理プラットフォームのCUDAを落とします。

現在Ver10まで出ていますが、TensorflowがVer10に対応していないためVer9を導入。

Installer typeはnetoworkだとうまくいかなかったとの情報がありましたが、自分は大丈夫でした。

ちょっと時間がかかりますが、ぱぱっとインストール


developer.nvidia.com

 

cuDNN 7.3.1 の導入

CUDA専用のDNNライブラリのcuDNNを落とします。

これはNVIDIA Developerにあらかじめ登録してないと落とすことができません。また登録申請からアカウントが使えるまで1日待ったので気長にお待ちを

https://developer.nvidia.com/rdp/cudnn-download

 

バージョンはCUDAに必ず合わせます。CUDA 9.0を入れたので、「..., for CUDA 9.0」のを選択

 

f:id:Collonville:20181014205133j:plain

これはインストーラーではなくフォルダがzipで送られます

 

cuDNNをCUDAに適用

cuDNNの中に入っているファイルをCUDAにディレクトリにコピーします。

CUDAは標準だと「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0」に入っているはずです。

 

f:id:Collonville:20181014205747j:plain

 

cuDNNにはbin, include, libの3つのフォルダがありますが、その中身を上記のCUDAの同じフォルダ名の中にコピー

 

qiita.com

 

システム環境変数の確認

ここで一旦、Pathがちゃんと通っているか確認します。

過去にCUDAを入れたことがあったりすると「CUDA_PATH」が違うバージョンを示している場合があるので要注意

 

f:id:Collonville:20181014210307j:plain

Pathにも以下が通っているか確認

f:id:Collonville:20181014210431j:plain

 

Tensorflow 1.11.0 の導入

Pythonの実行するAnacodaとVisual Codeは予めインストールしておいてください。

ちなみにpythonのバージョンは3.5で(3.6でも問題ないはず)

Visual Codeのターミナル画面で仮想環境を立ち上げ「pip install tensorflow-gpu」と打てばインストールしてくれます

TensorFlow

 

f:id:Collonville:20181014211002j:plain

 

Keras 2.2.4 の導入

こちらもターミナル画面で「pip install keras」と打って実行すれば完了

Keras Documentation

 

Scipyのバージョン下げ

普通ならばここで簡単なテストを走らせれば動きますが、自分の場合AnacondaかTensorflowを入れる段階でバージョンが違うScipyが入れられたらしくエラーを吐きました。

いろいろ試したところバージョンを1つ下げたもので動いてくれました

  1. conda list」でScipyのバージョンを確認
  2. pipとcondaで重複していないか確認。重複していれば両方とも消す
  3. pip install scipy==1.0.1」でバージョン指定したのをインストール

 

パッケージバージョン一覧

とまぁなんだかんだ、以下のようなパッケージになりました。

恐らくもっとすっきりにできると思いますが...

f:id:Collonville:20181014212507j:plain

 

MNISTの分類サンプルの実行

パスとバージョンを確認したうえで、DNN基本であるMINISTの分類を行います。

コードはkerasのサンプルから丸コピーしてください。

github.com

 

.pyコードを実行すると、うまくいけば以下のように現在のエポック、ロス等が表示されます。きちんと GTX 760で回していることも確認できたのでこれでOK!!

 

f:id:Collonville:20181014213112j:plain

 

 ちなみに1エポックで130秒ぐらいかかりました。そこまでdeepではないのでやっぱGTX 760ではこの先も結構時間がかかりそう

 

Tensorflowのビルド

Tensorflowを自前でビルドする際は別途手順が必要です。

バージョンの対応表は下記リンクの一番下のページにあります

Build from source on Windows  |  TensorFlow

 

コンパイルにBazelとMSYSが必要になります。こちらもちゃんとPATHが通っていることを確認してください。

Installing Bazel on Windows - Bazel

https://www.msys2.org/

またこちらもtensorflowでバージョンが指定されています。なんでもかんでも最新のを選ぶと後々めんどくさいので要注意。

 

 

では!いいDNNライフを!

FirebaseのReal Time DatabaseとC#を使ってとりあえずメッセージを送信してみる(1)

こんにちわ、ころんです!

 

内定先の懇親会で最近「Firebaseまじ神!」「Firebaseまじすごいよ」とよく聞くのでいじってみることにしました。

 

qiita.com

loco-partners.hateblo.jp

techlife.cookpad.com

 

ファイアァァアアアアア!!!とえいえばTomollow Land 2018でSalvatore Ganacciが無理やり(?)演出係にファイアーさせてるのがツボってますw

 

Firebaseへの登録

firebase.google.com

 

FirebaseはGoogleの傘下にあるので自分はGoogleアカウントでそのまま入れました。
右上にある「コンソールへ移動」をクリックし、「プロジェクトを追加」を選ぶ。

 

f:id:Collonville:20180917150019j:plain

 

プロジェクトの作成画面で、名前とリージョンを選び作成。今回は「FireBaseChat」で

リージョンはデフォルトでも特に問題ないかと。

Set a project location  |  Firebase

 

f:id:Collonville:20180917150100j:plain

 

するとプロジェクトのメイン画面に移ることができました!

f:id:Collonville:20180917150436j:plain

 認証の設定

Firebaseの魅力にユーザー認証が容易にできることがあります。

わざわざOAuthの認証メソッドを書く必要もないし、Firebaseのプロジェクトごとに認証方法を変えられます。

webbibouroku.com

今回は、分かりやすくするために「匿名」を選びます。

 

f:id:Collonville:20180917151527j:plain

 

DBの設定

今回はユーザーが投稿したメッセージ等を格納するデータベースの設定を行います。

 

プロジェクトのメイン画面の左側にある開発から「Database」-->「データベースの作成」を選択するとセキュリティルールの設定に移ります。

 

f:id:Collonville:20180917152531j:plain

 

今回は「テストモードで開始」を選択。これでDBの設定は終わりです。

 

f:id:Collonville:20180917152205j:plain

 

DBのシークレットキー

DBへのシークレットキーは、左画面の歯車マークから「プロジェクトの設定」-->「サービスアカウント」-->「以前の承認情報」から取得できます。

しかしながら、DBのシークレットは現在廃止されているようなので今後は「Firebase Admin SDK」からの設定が必要らしいです。

今回の動作には問題ないですが、ここについても調べてみます。

 

f:id:Collonville:20180917153411j:plain

 

DBのURL

データベースへのURLは「プロジェクトの設定」-->「全般」-->アプリ-->「ウェブアプリにFirebaseを追加」を選択することで確認できます。

 

f:id:Collonville:20180917154121j:plain

 

C#でコードを書くときにこのDBシークレットキーとURLが必要になるのでメモっておいてください!

 

C#プロジェクトの作成

みんな大好きVisual StudioからC#のコンソールアプリを作成します。

f:id:Collonville:20180917154455j:plain

 

C#でゴリゴリ書くのもいいですが、せっかくなのでFirebase REST APIをラッパーしたFireSharpを使います。

 

github.com

 

Visual Studioのパッケージマネージャーコンソールから「Install-Package FireSharp」と打ってインストール。

 f:id:Collonville:20180917161149j:plain

 

さてコードですが、ラッパーのおかげで単純にテキストを送信する内容だったらこの程度でできます。


AuthSecretとBasePathにさきほどメモったDBシークレットキーとURLを記入し、実行すると「Hello, Firebase!!!」がDBの「chats/」下に格納されます。

 

gistd1d30622b27851dbd2a657396cdbfbee

 

実行後にFirebaseプロジェクトのDatabaseを見ると「Realtime Database」が作成されていることが確認できます。

 

f:id:Collonville:20180917160517j:plain



中身を見ると、先ほど送信したメッセージが格納されています!!
あら簡単!!!

画像は「!!!」の部分が見切れていますがちゃんと入っているので安心を

f:id:Collonville:20180917160701j:plain

ちなみにコードのresonceのbodyを見ると各メッセージのIDが確認できます。

まとめ

今回は、Firebaseを使ってクライアントからサーバーにメッセージを格納する処理を作成しました。

単純ですが書いたコードは僅かで実現できたのは確かに便利!

 

ですがFirebaseの魅力はまだ発揮できていないので、次回からチャットサービスの作成までやっていきますね!!

Philips ソニッケアー Healthy White 先端部修理

いつも愛用しているPhilips電動歯ブラシが突然壊れました!
歯ブラシの先端と本体をつなぐ銀色の出っ張りがグラグラになり、超音波の振動が届かず

HealthyWhite ソニッケアー ヘルシーホワイト HX6719/43 | Sonicare

f:id:Collonville:20180710192257j:plain

 

保証書もどっかいったし、新しく買うのもなんかもったいない。
本体を振っていると明らかにパーツが取れてる音がしたので、これは直せそうだなと思ったので分解しちゃいますwww

開け方は下記のページを参考。自分は細いマイナスドライバーで「▼」と印刷されている部分に入れると割とすんなりキャップは取れました。

ソニッケアーの充電池を交換してみた

 

っで下の写真が本体です。やはりパーツが取れてました。

f:id:Collonville:20180710192347j:plain

Philipsソニッケアーの本体

どこのパーツだろと探してたら、明らかに不自然なへこみが。

f:id:Collonville:20180710193034j:plain

金属部のハの字がちょうどぴったりだったので、ハメて上からねじ止めすればグラグラしなくなりました。

f:id:Collonville:20180710193244j:plainこれで直ったー!と思って外装と合わせて動作確認がしましたが、またすぐ同じ部分が取れてぐらぐらに。

2つ上の写真のネジを見ると赤い付着物があります。どうやら接着剤?で固定していたようですが、超音波の振動で完全にはがれてしまったようです。

 

ってことでみんな大好き「アロンアルファ」でねじ部と頭に接着してしばらく放置。

f:id:Collonville:20180710193541j:plain

乾いた後、動作テストをして無事修理終了。施工してから3日たちましたが、今のところ大丈夫そうです!!

 

 

 

\チャンチャン/

 

 

Visual Studio Codeの設定を完全に削除する方法

普段からVSCodeを使っていますが、なぜかpythonに関する項目でsettings.jsonに「duplicate object key」が何百のエラーを出していました。

 

意地悪なことに、ユーザーが操作できない項目になっているのでダブってる項目を削除することもできず...


結果的にアンインストールして入れなおそうと思ったのですが、ただアンインストールするだけでは以前DLした拡張機能やsettings.jsonが残ったまま!

解決策

アンインストール後にフォルダを漁ってると「C:/Users/(ユーザー名)/」に「.vscode

というフォルダを発見。


どうやらこの中に過去の設定群が残ってるらしく、削除した後VS Codeを入れたら無事初期化してくれました。

 

 

(;´д`)

 

 

python「OSError: raw write() returned invalid length ... やで」

Numpyを使って行列計算の確認用にprint()を使っていたのですが、
ある日から突然エラーを吐くようになりました。

 

OSError: raw write() returned invalid length 4 (should have been between 0 and 2) 

 

数字はコードによって変わりますが、自分の場合は何回かprintされてから上記のようなエラーが出てきます。

 

解決策

下記を参考に修正しました。

 

qiita.com

 

下記のコードを記述すればエラーは消えますが、Anacondaを使っている人は
conda install -c anaconda win_unicode_console」を使ってパッケージを導入する必要があります。

 

import win_unicode_console
win_unicode_console.enable()

 

Win Unicode Console :: Anaconda Cloud