Open GENZITSU opened 1 year ago
日本と海外での仕事の進め方の違いを考察しているブログ。
普段仕事をする上で重要そうな話があったのでメモ
約束は「現時点でOK」という意味でしかない 海外ではこんなトラブル日常茶飯事 「すべて予定どおりコトが進むのを前提とし、正しい要求なら押し通せる」という考えは、とても日本的 納得がいかなくても、切り替えて交渉しなければ損するだけ 「予定通りにいかないのは日常茶飯事だから、だれかを責めてもしょうがない」 相手の落ち度を責めても交渉は有利にはならない 確実にしたいならカネを積んで契約すべし
日々刻々と状況が変わることは日常茶飯事なので、状況が変わったことを嘆き糾弾しても意味はなく、状況が変わることを念頭においた準備や、たじろがないでコトを進める胆力が必要なのかもしれない
LangChainのAgentがどのツールを使えば良いかをわかりやすくためにtoolのdescription文の改良に取り組んだスライド
タスククエリに関して呼び出されるべきツールの正解リストを事前に適宜しておき、実際にエージェントにタスクに依頼した時に想定ツールが呼ばれているかをチェックする。ここで、呼ばれなかったツールについてはdescriptionが悪いとしてLLMによる修正をさせているようだ。
タスクとクエリの対応を事前に記述しておくというのがアノテーションに相当するのだろうか?
本来アノテーションは最終的な結果に対して行うもので、やり方まで指定するのは特徴量エンジニアリングに相当しそうなのであまりスケールしなさそう。
また、目的のために利用するべきツールは複数種類あったりすると思うので、適切なツールの設定というのが難しそう。
End-to-Endに行うコトを考えるとツール選択を行うRetriverを、LLMの最終出力からbackpropとかした方がいいようにも思える。
平均値 + 3σで外れ値を検出より、中央値 + 2.5 MedADを使いましょうと提唱している論文。
MADとはmedian absolute deviaitionsの略で、中央値からの絶対誤差の中央値の値のことを言う模様。
有料論文だったので中身は読めてないけど、解説しているツイートがあったのでメモ
外れ値は実務に照らし合わせて決まってくるものなので、手法の1つでしかないけど、引き出しは多い方がいいかなと言う感じ。
並列ハイパラ探索アルゴリズムであるSuccesive Halvingについて解説している記事
2018年に提案されたものだが、直列型のハイパラ探索手法と異なり、各ハイパラ設定の実験を最後まで実行する前に探索を打ち切り別のパラメータ設定の実験を開始させられる点で時間的に効率が良いとのこと。
アルゴリズムの概要は以下
各ハイパラ設定の結果の共有を同期的に行う場合、その他の実験を待つ間がボトルネックになってしまうが、そこを非同期にしたのがAsynchronous Successive Halvingという手法
この手法では、各ハイパラによる実験が終わった後、すでにtop 1/Nが確定しているようなものがあればそれの深掘りを行い、そうでない場合はtop 1/Nを確定させるために別設定のハイパラを探索させるようにさせることで計算の待ち時間をなくす工夫を行っている。
2018年に提案されたものだが、直列型のものしか知らなかったので大変勉強になった。
LabelEncoderは元々目的変数を変換するためのメソッドで未知の数値が来た時に変化値の設定もできない。
説明変数の変換には、未知の数値が来た時の変換値の設定が可能なOrdinalEncoderを使おうとのこと。
LabelEncoderをラップして未知の説明変数を変換するコードを昔書いていたのだが、OrdinalEncoderなるものがあったとは...
succesive halving, Hyperband, BOHB, PBTといった異なる並列ハイパラ探索アルゴリズムを解説している記事
ハイパラ探索手法には直列型と並列型があることを知った上で読むと理解度が段違いだ...
類似ベクトルの検索の際に、自身のラベルを1、その他を0としてSVMを学習した上で、ベクトル同士の類似度を算出する手法を紹介している記事。
直感的には元のベクトルをカーネル空間に写像した上でベクトルの類似度を算出できるので、kNNより良さげな類似度が算出されそうだが、最初のラベル付の部分だけほんまにそれでいいのか?という感じ。
今回の記事では、kNNとSVMの両方のsimilaritiesを使った場合がよかったとのこと。
# from https://secon.dev/entry/2023/04/29/220000-langchain-svm-retriver/
# base: https://github.com/karpathy/randomfun/blob/master/knn_vs_svm.ipynb
from sklearn import svm
import numpy as np
from langchain.embeddings import OpenAIEmbeddings
def knn_top_k(query_emb, embs, k=10):
l2_embs = embs / np.sqrt((embs**2).sum(1, keepdims=True))
l2_query = query_emb / np.sqrt((query_emb**2).sum())
similarities = l2_embs.dot(l2_query)
sorted_index = np.argsort(-similarities)
res_index = sorted_index[1:k+1]
return res_index, similarities[res_index], -similarities
def svm_top_k(query_emb, embs, k=10):
X = np.concatenate([query_emb[None, ...], embs])
y = np.zeros(X.shape[0])
y[0] = 1
clf = svm.LinearSVC(class_weight='balanced', verbose=False, max_iter=10000, tol=1e-6, C=0.1)
clf.fit(X, y)
similarities = clf.decision_function(X)
sorted_index = np.argsort(-similarities)
res_index = sorted_index[1:k+1] - 1
return res_index, similarities[res_index + 1], -similarities[1:]
def get_query_emb(text):
emb = OpenAIEmbeddings().embed_query(text) # type: ignore
return np.array(emb)
def join_colon(num_list_a, list_b):
return [f'{a:.3f}: {b}' for a, b in zip(num_list_a, list_b)]
def knn_svm(text, embs, texts, k=5):
query_emb = get_query_emb(text)
knn_index, knn_similarities, _ = knn_top_k(query_emb, embs, k)
svm_index, svm_similarities, _ = svm_top_k(query_emb, embs, k)
print('query: ', text)
print('=== kNN ===')
print("\n".join(join_colon(knn_similarities, texts[knn_index])))
print('=== SVM ===')
print("\n".join(join_colon(svm_similarities, texts[svm_index])))
def hyblid_knn_svm(text_or_emb, embs, texts, k=5):
if isinstance(text_or_emb, str):
query_emb = get_query_emb(text_or_emb)
print('query: ', text_or_emb) # type: ignore
else:
query_emb = text_or_emb
# 全件取得する
knn_index, knn_similarities, knn_all_scores = knn_top_k(query_emb, embs, embs.shape[0])
svm_index, svm_similarities, svm_all_scores = svm_top_k(query_emb, embs, embs.shape[0])
# score を正規化する
knn_score_normalized = (knn_all_scores - np.mean(knn_all_scores)) / np.std(knn_all_scores)
svm_score_normalized = (svm_all_scores - np.mean(svm_all_scores)) / np.std(svm_all_scores)
# それぞれのスコアを足し合わせて、ハイブリッドなスコアを作る
hybrid_similarities = (knn_score_normalized + svm_score_normalized) / 2
hybrid_index = np.argsort(hybrid_similarities)[:k]
print('=== kNN ===')
print("\n".join(join_colon(np.sort(knn_score_normalized)[:k], texts[knn_index][:k])))
print('=== SVM ===')
print("\n".join(join_colon(np.sort(svm_score_normalized)[:k], texts[svm_index][:k])))
print('=== Hybrid ===')
print("\n".join(join_colon(hybrid_similarities[hybrid_index][:k], texts[hybrid_index][:k])))
ベクトル探索をする際に毎度毎度SVMを学習させるのは計算コストがなかなか無視できない気もするが、レスポンススピードが求められないケースだと性能が良さげになるので、選択肢に入りそう。
衛星画像の5倍超解像コンペの1位解法の共有
基本的なOSSモデルは2**N乗の超改造にしか対応していないため、4倍に拡大したあとBicubicで1.25倍に拡大しSSIMのロスを取るという構成を採用
色々な設定でモデルを作成し、アンサンブルを実施
特徴的なのは
超改造分野では現状Swin2SRというモデルが強いことが知れてよかった アンサンブルパートについてはめちゃくちゃ精度があがっているわけではないが、学習途中にデータ拡張の強度を変えることに類するテクがちゃんと効いてるのが面白い。
衛星画像の5倍超解像コンペの3位解法の共有
手法は1位解法と似たような感じ、こちらはcutblur/外部データを使っていない点が大きな差異か
任意の倍率に拡大可能なMeta-SRという手法を用いて4倍から5倍の拡大を試みたあ、今回は単純なリサイズを超えられなかったとのこと。
また、jpeg compression / jitterといった色を変える系の変換は超解像ではあまり効かない傾向があるらしい。
シングルモデルでちゃんと高い精度出しているのが好印象。
学習に用いたハイパラも詳しく載っていてとても参考になる。
衛星画像の5倍超解像コンペの2位解法の共有
その他の上位解法と同様に、epochの途中でデータ拡張を変更している。
RCANモデルを5倍超解像までできるように解像しているのと、MADGRADという珍しいoptimizerを利用しているのが目を引く
MADGRADというoptimizerは初耳だったが、shoopeeコンペの1stが使っていたoptimizerのようだ。
RCANというモデルは、SwinIRよりも若干性能が悪いみたいなのであえて使う必要はないかも知れない。
衛星画像の5倍超解像コンペの8位解法の共有
ベースのモデルは、ESRGANを利用。ESRGANのactivationはLReLUからSwishに変更し、ブロックごとに2倍(PixelShuffle)、2倍PixelShuffle)に拡大し最後はbilinearで拡大するようにした。
衛星画像に写っているものベースでstratified train test splitを実施するために画像の最大/最小/平均/分散を特徴量としたk-meansで15クラスへのクラスタリングを事前に実施。
このタスクでは大きなパッチサイズで長く学習させることで性能が上がる傾向あるようだ。
学習時間除いて10時間程度でこの順位はかなり凄そう。
裏技公開! AI映像解析で物体検出精度をあげる簡単テクニック
街路樹に隠れてしまった車の検出ミスをなくすために試したことが綴られているブログ
記事の中では交差点を通行する車を検出する際に、木陰の街路樹の後ろを通過する車の検出ミスが発生していた。
この問題は、検出に利用していたyolox_mをyolox_x(小さいものから順にnano, tiny, s, m, l, xがある)に変えてもむしろ悪化し、検出閾値の変更、トラッキングアルゴリズムのハイパラ調整でも変化がなかった模様。
唯一解像度を小さくすることで、若干の改善がみられたがモデル側の改善ではどうにも対応できなかったとのこと。 (解像度を小さくすると、車体のサイズやbboxの移動幅が小さくなるので同一のIDが割り当てられやすくなる...?) (解像度が変わっても検出アンカーサイズは変わらないから、余計な検出をしなくなるのだろうか?) (いずれにしても本質的な解決にはなってなさそうな?)
そこで筆者が考えたのが、街路樹の色の変更
黄色に塗ると黄色の車が通った時に問題になりそうだが、今回のケースでは改善。 動画を見てみると黒色の場合は、一つの車が物陰に隠れた瞬間二つに分離していたが、黄色の障害物だと1つの車として判定されるように変化している。
https://www.youtube.com/watch?v=4lCGYK2XCXI
コメント
塗る色は黄色じゃない方が良いのではという話もあるが、普通にトラッキングアルゴリズム側の問題な気がする。
進行方向に移動している際に、もの影に隠れてしまっただけで、二つの車に検出してしまうyoloxも問題だが、検出されたすべてのbboxにIDを割り振る必要があるのかも結構疑問。(たまたま検出されたものにidが振られるのもあれなので、数フレーム存在して初めてIDを振った方が良いケースもあり得るような?)
出典