Open GENZITSU opened 2 years ago
NLPコンペでとるべき基本戦略が述べられている良記事
自然言語処理コンペでは多くの人がhaggingface/transformersを元にモデルを組み立てることから初動で差がつきにくい。
考察されている理由
- 事前学習モデルの上にアーキテクチャ的な変更を加えてもスコアが改善されづらいことが経験的に知られている[要出典]。
- 画像コンペとは違い入力が離散値なので、data augmentation での工夫が難しい。
- 事前学習モデルを使うため、前処理でテキストのクレンジング・クリーニングなどの効果があまり期待できない。
- データ数が少ない場合は学習が不安定になりがちで、本質的な改善を確認しづらい。
そのため以下のようなアプローチを取るのが基本的に良い
- 多様なモデルでのアンサンブル
- さまざまな事前学習済みモデルを試す
- アンサンブルは序盤から組み込んでおく
アンサンブルによっては特殊な工夫を行わなければならない時があるので、先にパイプラインを作っておくと良いらしい
- 複数モデルの推論結果から hard voting で最終的な推論を決める
- トークンごとの logits を文字単位に展開し、文字単位でアンサンブルを行う
その他の戦略①: 外部データの利用
対象タスクと同じ/似ている外部データを利用して性能を上げたり、タスクは違うが教師なしデータとしてもってきたりなど
外部データに対して何らかの形でラベル付与して学習に用いることができると強いっぽい。
今年のコンペではpsudo labeling系が強かったとのこと。
その他の戦略①: headの部分の工夫
CommonLit Readability Prize | Utilizing Transformer Representations Efficiently で色々な head 例が紹介されています。 QAタスクでも、start/end を別々の Linear レイヤで予測するのではなく、end の予測に start の予測結果を利用する例がありました。 Coleridge Initiative - Show US the Data | 1st place solution: Metric learning and GPT
その他の戦略②: layerごとに学習率を変更する 浅いそうほど小さく、深いそうほど大きくする。headの部分だけ大きめに取るのもあり
その他の戦略③: Layer Re-Initialization headだけではなく、深いそうもまとめてinitializeする
その他の戦略④: Within-task pre-training
コンペの訓練データを使って事前学習モデルを MLM で更に pre-training を行った後、コンペのタスクで fine-tuning を行います。
知らないテクが多い、神記事だ。
common voiceデータを使った日本語音声認識モデルをwav2vec 2.0を通して実装する方法が丁寧に紹介されている
メモ
不均衡データ対策をcutmix x オーバーサンプリングにより行う手法の紹介記事
結果とablation
少数クラスのサンプルが、登場するコンテキストを増強しているという解釈になるんだろうか...
Unsupervised Keyphrase Extraction by Jointly Modeling Local and Global Contextという教師なしキーフレーズ抽出を試してみている記事。
この手法ではembeddingベースの手法とグラフベースの手法のいいとこ取りをしてキーフレーズを抽出する。
ただし、最初と最後の単語への重み付け少々やりすぎという側面があるらしいので、パラメータ調整は必須とのこと
メモ
じつは直面すべき課題は「内部品質の低さ」や「依存ライブラリのアップデートが間に合っていないこと」ではなく、そのような状況を生み出してしまった開発プロセスや組織設計にあり、「開発プロセスや組織設計をどう直すか」なのである、
プロダクトの品質を継続的に高く保つためには、プロダクトに向き合うだけでは足りなくて、それを生み出すプロセスや組織に向き合う必要がある。チームはそれぞれチームに向き合う必要があるし、チームを束ねる立場(これは上下ではなくて役割の違いだ)は各チームの組成をどのように行い、各チームがどのようにコラボレーションするかの設計に向き合わなければならない。
重てぇ言葉だ
ブログ中にある画像に対してimage captionをすることでseo対策をおこなえるのではないかを試みた記事。
試みは始まったばかりなので今後に期待。
なぜData Validaitonが重要になるかの説明から、Data Driftの分類、それらをどのように対処していくかが丁寧にまとめられている記事。
Data Validationは以下のような理由で重要
Data Driftの分類
どのように検知していくか?
ただし、これらのvalidationを逸脱した時に何をするべきかは事前に決めておかないと、結局アラートを出しても見られなくなる...
良記事だ。。。
最適輸送によるテキスト間距離計算において、単語の重み付け変更がもたらす影響を検証した記事。
以下の重み付けを検討
このPS-IDFという重み付けは以下のようなものらしい
PS-IDFは Soft TFIDF[Cohen+, IIWEB2003]という手法を参考に作成しました. Soft TFIDF は,TFIDFスコアを求めたい単語と類似する単語集合を取得し,それらの単語との類似度を重みとしたTFIDFスコアの加重平均を計算することでTFIDFスコアを求める手法です.これにより,ルックアップテーブルに存在しない単語であってもTFIDFスコアを算出することができます.
PS-IDFは,単語の音素列の類似度を考慮して“Soft”にIDFスコアを計算する手法です.式で表すと以下のようになります.
今回の検証ではIDFやPS-IDFが良かったとのこと
Soft-IDF, PS-IDF知らなかった。
あんまり、こうまとめることができなかったのだが、以下の言葉が響いた
その開発能力の源泉となるのは、チームやプロダクトに誇りを持って開発を続ける優秀なエンジニアたちだ。技術的負債の放置は、リードタイムや変更失敗率が悪化するというソフトウェアデリバリ面だけでなく、開発者体験、言い換えれば従業員エンゲージメントを悪化させる。これでは「プロダクト開発能力の差異化」の実現が遠のいてしまう。それだけに、技術的負債のマネジメントは、エンジニアリング組織を預かるマネージャーの重要な責務だと考えている。
メモ
最近上々したexawizards社の機械学習エンジニアたちがどのような組織構成をとっているかの紹介記事
組織人員
AI Frontier部は、エクサウィザーズの中でも特に機械学習エンジニアが集まっている組織です。機械学習エンジニアだけで現在50名弱程在籍しているのですが、「これは国内では最大クラスなのでは」と人事チームともよく話しています。
かつて組織が抱えていた課題
初期の課題: 組織が大きくなるにつれてアサインに関するエンジニアの不満が高まってきました。そこで1on1でエンジニアの話を聞きながら、EM(エンジニアリングマネージャー)がアサインをするという体制を取り入れました。
EM体制での課題:
こういった背景もあり、更なる組織成長のために現在のギルド制へと移って行ったとのこと。
各分野を牽引する人材がリーダーを務めるギルド制
ギルド制での業務
案件の実施: AIコンサルタントチームと連携を取りながら、領域の近いギルドが相談にのる形で実施。担当エンジニアが孤軍奮闘にならないような工夫を実施している。ギルドが主体となって独自R&Dをすることで案件がスタートすることもある。
知見の蓄積と共有: 知見が分散しがちという課題に対して、以下のような工夫を実施
案件に関するものでは、案件相談事の内容をwikiに蓄積する、実施中の案件レビューを行う、案件終了時にビジネスメンバー等も交え振り返りを行う、蓄積された知見をガイドラインとしてまとめる。 キャッチアップ系では、論文勉強会を行う、学会に参加し報告会を行う。 アウトプット系では、社内外に知見を発信する、よく使う技術をライブラリ化する、独自の学習済みモデルを作る、など。 これらはギルドとして自分たちで優先度を決め、一定の工数を使って主体的に取り組んでいます。
組織から一方的にミッションを与えるのではなく、組織のゴールと個人のゴールをつなげることを意識してチームをつくっています。これは、自律的なチームづくりをする上で、大切な考え方だと思います。
自分たちの仲間は自分たちで集めるという考え方のもと、採用もギルドで積極的に行っています。採用チームと連携しながらジョブディスクリプションを自分たちで書く、採用基準を考える、それに基づいた技術スクリーニング(口頭試問等)の作成、書類選考、技術面接、採用イベントの企画・参加、スカウト、なども自分たちで行っており、
今後
内的なものは、できるだけエンジニアが本来発揮できる価値創出に集中できるための基盤の整備です。MLOpsでいえば、Dev側の仕組みになります。エンジニアの意見を聞きながら実験管理・実験自動化の共通基盤を整備したり、ギルド発で知見を蓄積しながら効率的な開発ができるアプリを開発するなど、新しい取り組みが始まっています。組織を拡大しながら価値創出に集中できる仕組みを作ることで、より社会に貢献できる量が増えると考えています。
外的なものとしては、より着実に運用と社会実装を進めるため、MLOpsでいうOps側の取り組みを強化しています。実証実験等を通して導入する価値が検証されたものに対し、これまで以上のスピードで現場に導入したり、お客様もこれまで以上にモデルに触れながら現場で活用したりして頂けるよう、共通基盤を整えています。
最近上々したAI系ベンチャーの組織体制として非常に参考になる。
長く業務に従事しているとプロジェクト思考に囚われがちだが、プロダクト思考とプロジェクト思考を行ったり来たりすることが重要という趣旨の一連のツイートをようやくした記事。
プロジェクト思考とプロダクト思考の違い
プロジェクト思考: 期待を理解し、計画を立て、リソースを集め、その期待に応えるために行動を調整すること。 プロダクト思考: 動機を理解し、解決策を考え、その効果をシミュレーションし、望んだ効果に至る道筋を選ぶこと。
プロダクト思考から始めて、差別化された創造的な解決策にたどり着き、プロジェクト思考でその実現可能性を評価することが重要と何度となく気づきました。今日直面している制約と明日直面するかもしれない制約を考慮しつつ、プロジェクトにおける最終的なゴールと実現に向けてどう行動するかが、この思考プロセスの果てに明確になります。それが、決断力のある行動を可能にするのです。
プロダクト思考に長けるためには
プロダクト思考大事にしていきたい。 プロダクト思考にはシミュレーションが大事と書かれているのが意外。
誤分類コストを設定することで、分類モデルの閾値調整を行う方法を紹介している。
誤分類コストを考慮する方法は代表的には以下
- 通常の学習を行なったモデルの出力に対する検出閾値を、サンプルの誤分類コストに応じて変更する
- 学習データセットのクラス比率、あるいは重みを誤分類コストに応じて変更した上で通常の学習を行う
- 誤差関数などモデルの学習手法そのものに誤分類コストを組み込む
この記事では1番目の閾値調整の方法を紹介
誤分類コストを考慮した閾値は、簡単な不等式から求められる。
以下のような実装で閾値調整ができる
# from https://devblog.thebase.in/entry/2021/12/23/110000#%E9%96%BE%E5%80%A4%E3%81%AE%E8%AA%BF%E6%95%B4%E3%81%AB%E3%82%88%E3%82%8B%E8%AA%A4%E5%88%86%E9%A1%9E%E3%82%B3%E3%82%B9%E3%83%88%E3%81%AE%E5%8F%8D%E6%98%A0
threshold = (cost_matrix[1,0] - cost_matrix[0,0]) / (cost_matrix[1,0] - cost_matrix[0,0] + cost_matrix[0,1] - cost_matrix[1,1])
y_pred = (y_prob >= threshold).astype(int)
plot_confusion_matrix(y_test, y_pred, y_prob, cost_matrix)
当然誤分類コストを考慮した方が、単純な accuracyは下がることに注意
メモ
🐎 A fast implementation of the Aho-Corasick algorithm using the compact double-array data structure.
メモ
XGBoostには特徴量が増加するなら、出力も増加することを制約として与えることができる、monotone_constraints
というパラメータが存在する。
このパラメータは1の時に単調増加制約を課し、-1の時に単調減少制約を課す。
# from https://jp.corp-sansan.com/mimi/2018/02/monotonic_constraints.html
param['monotone_constraints'] = '(0,1,0,-1,0)'
model = xgb.train(param, dtrain, num_round)
この記事では、単調増加制約を応用し、モデルのキャリブレーションを実施している。
# from https://jp.corp-sansan.com/mimi/2018/02/monotonic_constraints.html
p_valid = clf.predict_proba(x_valid)[:, 1]
# Isotonic regression
cal_iso = IsotonicRegression(out_of_bounds='clip')
cal_iso.fit(p_valid, y_valid)
# XGBoost
cal_xgb = xgb.XGBClassifier(
max_depth=3,
learning_rate=0.05, n_estimators=100,
monotone_constraints='(1)'
)
cal_xgb.fit(p_valid.reshape(len(p_valid), 1), y_valid)
あまり実務で使うことはないかもしれないがメモ
異常検知手法の一つとしてAdaptive Resonance Theoryを紹介している記事。
名前はぎょうぎょうしいがやっていることは、階層型クラスタリングに近い。
このアルゴリズムはデータを入れる順番が結果に影響を与えるので、複数回実行して結果を見る必要がある。
また、データ間の距離の定義と閾値の設定に敏感とのこと。
実装にはartlearn
というライブラリが利用できる模様。
記事中では以下のようなアルゴリズムが紹介されていた。
名前負けしている感はあるが持ち手としてメモ
Amazon SageMakerのプロダクション環境での活用事例がまとめられている。
紹介されている機能は以下。
いつか参考にすることがありそうなのでメモ
早稲田大学から日本語版robertaが出ていた。
This is a Japanese RoBERTa base model pretrained on Japanese Wikipedia and the Japanese portion of CC-100.
メモ
jaxをベースとしたdeep learning用ライブラリhaikuとjmpを用いて、半精度学習を行う実装の紹介記事。
jaxはjitコンパイルしないと、破滅的に遅くなるので注意が必要らしい。
結果は以下
実装はまぁまぁ複雑だが、今後参考とするためにメモ
pytorch & XNNPACKでモバイル推論する際はchannel last formatにするのが効率的だよという紹介記事。
# from https://pytorch.org/blog/tensor-memory-format-matters/
## Outputs (on an Intel Core i9 CPU):
# Runtimes for torchscripted model:
# Contiguous: 1.6711160129999598
# Channels-Last: 1.6678222839999535
# Runtimes for mobile-optimized model:
# Contiguous: 0.5712863490000473
# Channels-Last: 0.46113000699995155
CS的な背景としては、配列をrow-majorで持つか、column-majorで持つかの話が関係しており、基本的にrow-majorで持つ場合はrow-majorで値の探索をするのが最も効率的であるという、背景がある。
# from https://pytorch.org/blog/tensor-memory-format-matters/
s = 70
Time for loop1: 77.0687ms ← row major
s = 70
Time for loop2: 1219.49ms ← column major
ここまで差が出る要因はD1 cache hit率が関係しているとのこと。
loop 1の chachhe hit率
# from https://pytorch.org/blog/tensor-memory-format-matters/
==3299700==
==3299700== I refs: 643,156,721
==3299700== I1 misses: 2,077
==3299700== LLi misses: 2,021
==3299700== I1 miss rate: 0.00%
==3299700== LLi miss rate: 0.00%
==3299700==
==3299700== D refs: 160,952,192 (160,695,444 rd + 256,748 wr)
==3299700== D1 misses: 10,021,300 ( 10,018,723 rd + 2,577 wr)
==3299700== LLd misses: 10,010,916 ( 10,009,147 rd + 1,769 wr)
==3299700== D1 miss rate: 6.2% ( 6.2% + 1.0% )
==3299700== LLd miss rate: 6.2% ( 6.2% + 0.7% )
==3299700==
==3299700== LL refs: 10,023,377 ( 10,020,800 rd + 2,577 wr)
==3299700== LL misses: 10,012,937 ( 10,011,168 rd + 1,769 wr)
==3299700== LL miss rate: 1.2% ( 1.2% + 0.7% )
loop2のcache hit率
# from https://pytorch.org/blog/tensor-memory-format-matters/
==3300389==
==3300389== I refs: 643,156,726
==3300389== I1 misses: 2,075
==3300389== LLi misses: 2,018
==3300389== I1 miss rate: 0.00%
==3300389== LLi miss rate: 0.00%
==3300389==
==3300389== D refs: 160,952,196 (160,695,447 rd + 256,749 wr)
==3300389== D1 misses: 160,021,290 (160,018,713 rd + 2,577 wr)
==3300389== LLd misses: 10,014,907 ( 10,013,138 rd + 1,769 wr)
==3300389== D1 miss rate: 99.4% ( 99.6% + 1.0% )
==3300389== LLd miss rate: 6.2% ( 6.2% + 0.7% )
==3300389==
==3300389== LL refs: 160,023,365 (160,020,788 rd + 2,577 wr)
==3300389== LL misses: 10,016,925 ( 10,015,156 rd + 1,769 wr)
==3300389== LL miss rate: 1.2% ( 1.2% + 0.7% )
メモ
light gbmのlinear_treeというパラメータについて
どうやらデータが素な場合はこのパラメータをTrueにしておくと良いらしい。
コメント
精度が上がらないときに試してみよう。
出典
元ツイート