目次
背景
- いくつかの画像分類の機械学習プロジェクトを経験してきて思ったこと
結論
- 期待値を下げろ
- DNNのモデルなんて先行研究があってもどうなるかはわからない
- サンドボックスの理想的な環境で結果が出ても、Sim2Realに進んだらうまく行かない事が多い
- 人より精度が高かったら導入してもらうように説明するべき
- 機械の期待値を下げて、導入してもらうのが大切
- くれぐれもDNNで何でもできると説明するのはよすべき
- 学習データは絶対に生成する
- 生成データ(synthetic data)が一番大切
- それを確率的に生成するので、入力画像の分布をコントロールする
- 下地を寄せる (例えば、自動生成した画像の背景など)
- ノイズを入れる
- 文字のフォントを合わせる
- 自動運転だって何だって、うまく行くプロジェクトはそうなる
- これができないと、残念ながらPDCAを高速に回せない
- 画像の特徴
- PNGとJPGでは分布が異なる
- Y軸でLog、X軸は0~255のPixelでヒストグラムを作る
- 例えば、文字の中心は黒(0)で輪郭は(1~255)になる
- それがjpgだと0が弱い。他方、pngは非圧縮なので0が強い
- そうすると、二値化したときに変化がでる
- なので、最頻値を二値化するときはthreasholdで見る
- 最頻値の理由
- 白と黒の図面の場合は、最も出現するのが白のため
- 経験的に決めていることもある
- 指標は一つにフォーカスする
- 例えば、取るのがそもそも難しい課題は、最初はRecallにフォーカスするとか
- Recallで間違ってもいいので欲しい画像を取れたら、あとあといらない物を消す前処理を入れる
- Precisionは低くてもやる
- 課題の選択
- 全部の課題に対処することはできない
- エッジケースを除いて、正常系で、さらに簡易的なものを選択する
- 別の言い方だと、分母を絞る
- 90点と50点だと印象が全然違う
- 先にテストの問題を自分で狭めて高いスコアを出せるように調整する
- 特徴
- RGBで特徴量を入れる
- 普通の画像で入れるよりも、RGBで解く超量をまとめる前処理をしてモデルに入れる
- 精度と速度
- 精度を優先したあとに、処理速度を最適化する
- ONNX Runtimeで最適化する
- 失敗時
- エラーについて考察をする(エラーアナリシス)
- $時間軸 \times 課題軸$でReportをまとめる
- 例
- 過去の課題 (past tasks)
- 今週の課題 (present tasks)
- 今週の進捗 (present progress)
- 今週の改善点 (present conclusion)
- 今後のスケジュール (future tasks)
- 課題ベースで話す
- スケジュールベースで話す
- 例
- 定量的と定性的に
- 数量的に判断する
- データが中心
- パターンの整理 (ルールベースの場合は)
- 特に、お客さん自体もルールを完全に把握していない時がある
- 情報を整理して交通整理することは大切
- データの選別の基準
- 事業ドメインやスコープの内・外
- コアユーザー vs. ライトユーザーのデータ
- 標準データ(ISO標準) vs. 非標準データ
- フィージビリティ
- できる所をやる => 費用対効果high
- できない所をやらない => 費用対効果low
- ベースラインを作る
- まずは簡単なやり方でベースラインを作る
- ムーンショットを狙うと、うまく行かなかった時にソフトランディングできない
- そのため、予め安全地帯を確保するのが大切
- 複数の手段を用意して、予め失敗に備える
- アルゴが優先
- 機械学習のDNNよりアルゴを優先するべき
- もしくは、DNNよりLLMを優先
- なぜなら、DNNは未知の変数が多く汎化性能も不明な事が往々にして発生する
- 結果をCherry-pickしたり、一面的に見て精度を判断してしまう事が多い
- はじめから堅く古典的アルゴで攻めて、もしくは万能のLLMで攻める
- それでも要件を満たせないなら、DNNに進む
- DNNの場合はデータが命なので、どれだけデータを集められるかの戦いになる
- 課題もモデルもless is more
- 例えば、XXXの価格予測の問題
- まず価格を簡単なものと難しいものに分ける
- これは誰でもできる
- しかし本質は、モデルを2つに分けた方がいい
- つまり、そもそも混合モデルであるという前提を持つ
- なぜこうするかというと、1つのモデルだと外した時にエラーアナリシスがやりにくいから
- つまり、めんどくさいかもしれないが、予めモデル自体も分解する
- すれば、重み調整やモデルの調整やデバッグもしやすく、本当の課題が見やすくなる
- EdgeではモデルはC++で動かす
- Edgeで早く動かしたいなら、まずはMobileNetとかの軽いモデルを選ぶ
- その上で、軽いランタイムを使ってC++で高速に動かす
- くれぐれも、Pythonで動かさないように
- Server-sideのLLMの場合は
- Prompt Engineeringをする
- 特にFew-shotが絶大
- さらに、CoTで分割統治法的に課題をStepByStepで解くのも大切
- 本質的にはその2つが一番効く
- Context engineeringも大事
- Messageは圧縮するべき
- これをしないと、メッセージが長くなると確実にやり取りがバグる
- Cacheを使う
- 特にAWS BedrockのClaude系のモデルはCacheが強い
- System Promptとかは、経験上9割引になるので有効活用する
- Routerパターンと特化Agentを使う
- 一つのAgentに全部やらせるのは難しいのでAgentを複数用意し、Router Agentに振り分けさせるのがいい
- Promptも最適化する事もできる
- Prompt Engineeringは限界がある
- たとえRouterパターンやStrands-Agentが持つGraph機能やらで分割しても限界がある
- 本質的にはLoRAなどでファインチューニングするべき
- Agentは確率的に間違えるのでPromptのチューニングは限界がある
- SSEやNDJSONでStream処理するのは限界がある
- structured outputをjson一つに対して行えないので、一度Agentが結果を間違えるとめんどくさくなる
- シナリオテストをたくさん実行するのと、fallback用の処理がないと厳しい
- 間違えたらリトライする仕組みを入れる必要がある
- Prompt Engineeringをする
まとめ
- 色々なパターンがあるが、失敗しないと学ばなないことが多い
- セルフニューラルネットワークの学習は続くだろう
