Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

almost weekly useful materials - 05/10 - #132

Open
GENZITSU opened this issue Apr 26, 2023 · 12 comments
Open

almost weekly useful materials - 05/10 - #132

GENZITSU opened this issue Apr 26, 2023 · 12 comments

Comments

@GENZITSU
Copy link
Owner

No description provided.

@GENZITSU
Copy link
Owner Author

GENZITSU commented Apr 26, 2023

裏技公開! AI映像解析で物体検出精度をあげる簡単テクニック

街路樹に隠れてしまった車の検出ミスをなくすために試したことが綴られているブログ

記事の中では交差点を通行する車を検出する際に、木陰の街路樹の後ろを通過する車の検出ミスが発生していた。

スクリーンショット 2023-04-26 23 50 32

この問題は、検出に利用していたyolox_mをyolox_x(小さいものから順にnano, tiny, s, m, l, xがある)に変えてもむしろ悪化し、検出閾値の変更、トラッキングアルゴリズムのハイパラ調整でも変化がなかった模様。

スクリーンショット 2023-04-26 23 46 10

スクリーンショット 2023-04-26 23 46 17

唯一解像度を小さくすることで、若干の改善がみられたがモデル側の改善ではどうにも対応できなかったとのこと。
(解像度を小さくすると、車体のサイズやbboxの移動幅が小さくなるので同一のIDが割り当てられやすくなる...?)
(解像度が変わっても検出アンカーサイズは変わらないから、余計な検出をしなくなるのだろうか?)
(いずれにしても本質的な解決にはなってなさそうな?)

スクリーンショット 2023-04-26 23 46 42

そこで筆者が考えたのが、街路樹の色の変更

スクリーンショット 2023-04-26 23 50 49

黄色に塗ると黄色の車が通った時に問題になりそうだが、今回のケースでは改善。
動画を見てみると黒色の場合は、一つの車が物陰に隠れた瞬間二つに分離していたが、黄色の障害物だと1つの車として判定されるように変化している。

スクリーンショット 2023-04-26 23 50 56

https://www.youtube.com/watch?v=4lCGYK2XCXI

コメント

塗る色は黄色じゃない方が良いのではという話もあるが、普通にトラッキングアルゴリズム側の問題な気がする。

進行方向に移動している際に、もの影に隠れてしまっただけで、二つの車に検出してしまうyoloxも問題だが、検出されたすべてのbboxにIDを割り振る必要があるのかも結構疑問。(たまたま検出されたものにidが振られるのもあれなので、数フレーム存在して初めてIDを振った方が良いケースもあり得るような?)

出典

@GENZITSU
Copy link
Owner Author

海外で日本のやり方を押し通そうとするとどうなるか

日本と海外での仕事の進め方の違いを考察しているブログ。

普段仕事をする上で重要そうな話があったのでメモ

約束は「現時点でOK」という意味でしかない
海外ではこんなトラブル日常茶飯事
「すべて予定どおりコトが進むのを前提とし、正しい要求なら押し通せる」という考えは、とても日本的
納得がいかなくても、切り替えて交渉しなければ損するだけ
「予定通りにいかないのは日常茶飯事だから、だれかを責めてもしょうがない」
相手の落ち度を責めても交渉は有利にはならない
確実にしたいならカネを積んで契約すべし

コメント

日々刻々と状況が変わることは日常茶飯事なので、状況が変わったことを嘆き糾弾しても意味はなく、状況が変わることを念頭においた準備や、たじろがないでコトを進める胆力が必要なのかもしれない

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Apr 27, 2023

LangChain Toolsの運用と改善

LangChainのAgentがどのツールを使えば良いかをわかりやすくためにtoolのdescription文の改良に取り組んだスライド

タスククエリに関して呼び出されるべきツールの正解リストを事前に適宜しておき、実際にエージェントにタスクに依頼した時に想定ツールが呼ばれているかをチェックする。ここで、呼ばれなかったツールについてはdescriptionが悪いとしてLLMによる修正をさせているようだ。

スクリーンショット 2023-04-27 14 51 05

スクリーンショット 2023-04-27 14 51 29

スクリーンショット 2023-04-27 14 51 40

スクリーンショット 2023-04-27 14 51 58

コメント

タスクとクエリの対応を事前に記述しておくというのがアノテーションに相当するのだろうか?
本来アノテーションは最終的な結果に対して行うもので、やり方まで指定するのは特徴量エンジニアリングに相当しそうなのであまりスケールしなさそう。
また、目的のために利用するべきツールは複数種類あったりすると思うので、適切なツールの設定というのが難しそう。

End-to-Endに行うコトを考えるとツール選択を行うRetriverを、LLMの最終出力からbackpropとかした方がいいようにも思える。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Apr 27, 2023

Detecting outliers: Do not use standard deviation around the mean, use absolute deviation around the median

平均値 + 3σで外れ値を検出より、中央値 + 2.5 MedADを使いましょうと提唱している論文。

MADとはmedian absolute deviaitionsの略で、中央値からの絶対誤差の中央値の値のことを言う模様。

コメント

有料論文だったので中身は読めてないけど、解説しているツイートがあったのでメモ

外れ値は実務に照らし合わせて決まってくるものなので、手法の1つでしかないけど、引き出しは多い方がいいかなと言う感じ。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 1, 2023

Massively Parallel Hyperparameter Optimization

並列ハイパラ探索アルゴリズムであるSuccesive Halvingについて解説している記事

2018年に提案されたものだが、直列型のハイパラ探索手法と異なり、各ハイパラ設定の実験を最後まで実行する前に探索を打ち切り別のパラメータ設定の実験を開始させられる点で時間的に効率が良いとのこと。

アルゴリズムの概要は以下

  1. 計算資源Nに各ハイパラ設定を割り振る
  2. 各ハイパラ設定による学習を1単位進める
  3. 1単位学習進めた時点で、top 1/Nだけ残して、その他の設定による学習をストップ
  4. 残ったハイパラ設定に対して1 * N 単位学習を進めて、top 1/Nだけ残して、その他の設定による学習をストップ
  5. その次は1 * N * N単位学習を進めて、以下同様に進行させていく

スクリーンショット 2023-05-01 15 13 35

各ハイパラ設定の結果の共有を同期的に行う場合、その他の実験を待つ間がボトルネックになってしまうが、そこを非同期にしたのがAsynchronous Successive Halvingという手法

この手法では、各ハイパラによる実験が終わった後、すでにtop 1/Nが確定しているようなものがあればそれの深掘りを行い、そうでない場合はtop 1/Nを確定させるために別設定のハイパラを探索させるようにさせることで計算の待ち時間をなくす工夫を行っている。

スクリーンショット 2023-05-01 15 17 17

コメント

2018年に提案されたものだが、直列型のものしか知らなかったので大変勉強になった。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 1, 2023

Python: scikit-learn の LabelEncoder を説明変数の変換に使うのは誤り

LabelEncoderは元々目的変数を変換するためのメソッドで未知の数値が来た時に変化値の設定もできない。

説明変数の変換には、未知の数値が来た時の変換値の設定が可能なOrdinalEncoderを使おうとのこと。

コメント

LabelEncoderをラップして未知の説明変数を変換するコードを昔書いていたのだが、OrdinalEncoderなるものがあったとは...

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 1, 2023

機械学習におけるハイパーパラメータ最適化の理論と実践 Part.2

succesive halving, Hyperband, BOHB, PBTといった異なる並列ハイパラ探索アルゴリズムを解説している記事

スクリーンショット 2023-05-01 15 41 04

スクリーンショット 2023-05-01 15 41 13

スクリーンショット 2023-05-01 15 41 22

スクリーンショット 2023-05-01 15 41 31

スクリーンショット 2023-05-01 15 41 51

コメント

ハイパラ探索手法には直列型と並列型があることを知った上で読むと理解度が段違いだ...

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 1, 2023

SVMを使った類似 embeddings 検索 - kNN ではない類似検索の選択肢

類似ベクトルの検索の際に、自身のラベルを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を学習させるのは計算コストがなかなか無視できない気もするが、レスポンススピードが求められないケースだと性能が良さげになるので、選択肢に入りそう。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 2, 2023

Solafune の衛星画像の超解像コンペで 1 位を獲得しました

衛星画像の5倍超解像コンペの1位解法の共有

ベースモデル

基本的なOSSモデルは2**N乗の超改造にしか対応していないため、4倍に拡大したあとBicubicで1.25倍に拡大しSSIMのロスを取るという構成を採用

スクリーンショット 2023-05-02 22 39 31

最終的な解放

色々な設定でモデルを作成し、アンサンブルを実施

スクリーンショット 2023-05-02 22 41 25

特徴的なのは

  • Lion Optimizerの採用
  • 4倍 x 2倍した後に0.625倍する
  • cutblurによるデータ拡張 (衛生分野でよく使われているやつ)
  • AWP
  • 練馬区の航空写真データセットの活用
  • 学習中に利用するデータを変更する

スクリーンショット 2023-05-02 22 45 14

コメント

超改造分野では現状Swin2SRというモデルが強いことが知れてよかった
アンサンブルパートについてはめちゃくちゃ精度があがっているわけではないが、学習途中にデータ拡張の強度を変えることに類するテクがちゃんと効いてるのが面白い。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 2, 2023

Solafune 超解像度化コンペ(5倍)3位解法

衛星画像の5倍超解像コンペの3位解法の共有

手法は1位解法と似たような感じ、こちらはcutblur/外部データを使っていない点が大きな差異か

スクリーンショット 2023-05-02 23 03 10

任意の倍率に拡大可能なMeta-SRという手法を用いて4倍から5倍の拡大を試みたあ、今回は単純なリサイズを超えられなかったとのこと。

また、jpeg compression / jitterといった色を変える系の変換は超解像ではあまり効かない傾向があるらしい。

コメント

シングルモデルでちゃんと高い精度出しているのが好印象。

学習に用いたハイパラも詳しく載っていてとても参考になる。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 2, 2023

【solafune:5x Super-resolution of Satellite Images】private 2nd

衛星画像の5倍超解像コンペの2位解法の共有

その他の上位解法と同様に、epochの途中でデータ拡張を変更している。

RCANモデルを5倍超解像までできるように解像しているのと、MADGRADという珍しいoptimizerを利用しているのが目を引く

スクリーンショット 2023-05-02 23 12 50

コメント

MADGRADというoptimizerは初耳だったが、shoopeeコンペの1stが使っていたoptimizerのようだ。

RCANというモデルは、SwinIRよりも若干性能が悪いみたいなのであえて使う必要はないかも知れない。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented May 2, 2023

[solafune] 衛星画像の5倍超解像度化 (for OSS) の解法

衛星画像の5倍超解像コンペの8位解法の共有

ベースのモデルは、ESRGANを利用。ESRGANのactivationはLReLUからSwishに変更し、ブロックごとに2倍(PixelShuffle)、2倍PixelShuffle)に拡大し最後はbilinearで拡大するようにした。

衛星画像に写っているものベースでstratified train test splitを実施するために画像の最大/最小/平均/分散を特徴量としたk-meansで15クラスへのクラスタリングを事前に実施。

このタスクでは大きなパッチサイズで長く学習させることで性能が上がる傾向あるようだ。

コメント

学習時間除いて10時間程度でこの順位はかなり凄そう。

出典

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant