2024年4月17日水曜日

Virtual-logit Matching

 [2203.10807] ViM: Out-Of-Distribution with Virtual-logit Matching (arxiv.org)

DNNの重みとバイアスを利用して固有値分解時の平均を除去する効果を狙った(と思われる)所がこの手法の勘所でしょうか。イマイチすっきりしません。

分散共分散行列を作成するのに GPU から CPUに戻しています。sklearn を使用しているので時間がかかるのが難点です。

以下、主要部分です。

特徴量の固有ベクトルを求める。
-> バイアスを取り除いた特徴量を作成する。
-> 特徴量の原点を計算。
固有値分解は分散共分散行列を利用。

from sklearn.covariance import EmpiricalCovariance
print('computing principal space...')
    ec = EmpiricalCovariance(assume_centered=True)
    ec.fit(feature_id_train - u)
    eig_vals, eigen_vectors = np.linalg.eig(ec.covariance_)
    NS = np.ascontiguousarray(
        (eigen_vectors.T[np.argsort(eig_vals * -1)[DIM:]]).T)

残差||xPT||を固有ベクトルへの射影時の離れ具合とみなし、OOD検出に利用している。残差が最大のロジットと比較して非常に小さい場合、SoftMaxでロジットのノイズに埋もれてしまう。スケールを補正するために、α=最大ロジットの平均/残差の平均を求める。

print('computing alpha...')
    vlogit_id_train = norm(np.matmul(feature_id_train - u, NS), axis=-1)
    alpha = logit_id_train.max(axis=-1).mean() / vlogit_id_train.mean()
vlogit_ood = norm(np.matmul(feature_ood - u, NS), axis=-1) * alpha


LogicOOD

このフレームワークの特徴は、DNNをモジュールとして組み合わせている点と人の判断が加わる点でしょう。

モジュール化によりシステムをインクリメンタルに構築することができ、要求に合わせてカスタマイズできるという利点を主張されています。例えば、知覚システムφに概念検出器f′を追加することができ、その結果、状態z′∈Z′を持つ拡張知覚システムφ′を作ることができる、と。計算時間はかかりそうですが容易にアンサンブルに持ち込めます。

環境構築はシビア。固定のVerでないと動かない、あるライブラリを入れるとTorchも上がり、依存関係が壊れる、など。欲張らなければ問題ないのですが。

OODの判定
outlier(x) = 1 if Df(x) >= τ, 0 else
Df (x) = -max Softmax: OOD detector

Logic
Dφ(x, S):outlier score = 0 if φ(x) ∈ S, τ else
φ(x) = f1(x), ..., fN(x) ∈ Z: predicted state for some input x.
S: 知識ベース(KB)に格納される制約条件

推論システムは推論エンジン
satKB : Z → {0, 1}
を実装しており、与えられた状態zが知識ベース内のすべての公式Sを満たすかどうか=KBを満たす状態とそうでない状態に効果的に分割する。

LogicOOD
D'φ(x, S):outlier score = Σi1,N[λDfi(x)] if φ(x) ∈ S, τ else
Dfi(): OOD detector for model fi
λi: weighting coefficients
Note: this method does not require example outliers during training.

LogicOOD+
An additional concept detector that is trained with example outliers to distinguish between IN and OOD.

T-LogicOOD
temperature-calibrated concept detectors.

ARPL+CS

ARPL (Adversarial Reciprocal Point Learning) (Chen et al., 2020a; 2021)

ARPL
データ、空間
DL: labeled samples ={(x1,y1),...,(xn,yn)}
DLk∈ Sk: positive  training  data, category k
DL≠k∈ Okpos:  negative  training  data, category !=k
DU∈ Oneg: potential  unknown  data
Sk: deep embedding space of category k
Ok: open space of category k, Okpos ∪ Okneg:
Okpos: positive open space from other known classes
Okneg: negative open space  as the remaining infinite unknown space 

クラスKの全サンプルにおいて特徴量空間で表現される点からからPkまでの距離は、他のクラスや未知クラスにおけるどのサンプルのPkまでの距離よりも大きくなる。
max(ζ(DL≠k∪DU,Pk))≤d,∀d∈ζ(DkL,Pk)
d(C(x),Pk) =de(C(x),pki)−dd(C(x),Pk)
de(C(x),Pk) =1/m·‖C(x)−Pk‖22
dd(C(x),Pk) =C(x)·Pk
ζ(·,·): calculates the set of distances of all samples between  two  sets
Pk: reciprocal point of category k, learnable parameter
m: dimension
C: deep embedding function, embedding feature

実装
class Dist(nn.Module):
    def __init__(self, num_classes=10, num_centers=1, feat_dim=2, init='random'):
        super(Dist, self).__init__()
        self.feat_dim = feat_dim
        self.num_classes = num_classes
        self.num_centers = num_centers
        self.centers = nn.Parameter(torch.Tensor(num_classes * num_centers, self.feat_dim))
    def forward(self, features, center=None, metric='l2'):
        if metric == 'l2':
            f_2 = torch.sum(torch.pow(features, 2), dim=1, keepdim=True)
            if center is None:
                c_2 = torch.sum(torch.pow(self.centers, 2), dim=1, keepdim=True)
                dist = f_2 - 2*torch.matmul(features, torch.transpose(self.centers, 1, 0)) + torch.transpose(c_2, 1, 0)
            else:
                c_2 = torch.sum(torch.pow(center, 2), dim=1, keepdim=True)
                dist = f_2 - 2*torch.matmul(features, torch.transpose(center, 1, 0)) + torch.transpose(c_2, 1, 0)
            dist = dist / float(features.shape[1])
        dist = torch.reshape(dist, [-1, self.num_classes, self.num_centers])
        dist = torch.mean(dist, dim=2) 

Class ARPLoss(nn.CrossEntropyLoss):
    def __init__(self, **options):
        self.Dist = Dist(num_classes=options['num_classes'], feat_dim=options['feat_dim'])
        self.points = self.Dist.centers
        self.radius = nn.Parameter(torch.Tensor(1))
        self.radius.data.fill_(0)
        self.margin_loss = nn.MarginRankingLoss(margin=1.0)
    def forward(self, x, y, labels=None):
        dist_dot_p = self.Dist(x, center=self.points, metric='dot')
        dist_l2_p = self.Dist(x, center=self.points)
        logits = dist_l2_p - dist_dot_p
        loss = F.cross_entropy(logits / self.temp, labels)
        center_batch = self.points[labels, :]
        _dis_known = (x - center_batch).pow(2).mean(1)}
        loss_r = self.margin_loss(self.radius, _dis_known, target)
        loss = loss + self.weight_pl * loss_r


softmax function
p(y=k|x,C,P) = eγ**d(C(x),Pk) / ∑i=1N{eγ**d(C(x),Pi)}
γ: hyperparameter, default = 1.0

損失
Lc(x;θ,P) =−log p(y=k|x,C,P) : pytorch の CrossEntropyLoss 実装
Lo(x;θ,Pk,Rk) =max(de(C(x),Pk)−R,0)
L:joint loss L = Lc + λ·Lo.
Lc: Classifire loss
Lo: loss, open space risk
λ: weight of the adversarial open space riskmodule, default = 0.1
θ: parameters in the convolutional layers, learnable parameters
R: parameters in the losslayers, learnable margin, learnable parameters


ARPL+CS
敵対的画像の利用
CS:Confusing Samples as DU

The discriminator is optimized to discriminate the real and generated samples:
maxD{1/n∑i=1n[logD(xi) + log(1−D(G(zi)))]}
x=G(z)
D:X →[0,1] represents the probability of sample x being from the real distribution or a fakedistribution. 

The generator is optimized by:
maxG{1/n∑i=1n[logD(G(zi)) +β·H(zi,P)], (18)=(16)+(17)
β: hyperparameter, default = 0.1
H(zi,P) =−1/N∑k=1N{S(zi,Pk)·log(S(zi,Pk))}: information entropy function
すべての逆数点の距離をバランスさせ、OGに近くなるようなサンプルを生成。
生成されたサンプルが既知のサンプルの境界から遠い場合、式(16)の損失大。
生成されたサンプルが既知のクラスに近い場合、式(17)の損失大。

The classifier C is optimized by the generated confusing samples as:
minC{1/n∑i=1n[L(xi,yi)−β·H(zi,P)], (19)
Note that the known samples and generated samplesare processed independently in Eq.(19). 

ABNは、異なるドメインに属する特徴に対して別々のBNを保持することにより、混合分布を分離し、紛らわしいサンプルの負の影響を効果的にブロックする。


その他

図1:既知サンプルの特徴量と異なる未知サンプルの特徴量の重なりを減らすことで、認識を向上させる。アプリケーションでは、様々な未知サンプルと既知サンプルを最適に分離するスコア閾値を選択する必要がある。残念ながら、(b) Softmax (c) Prototype Learningのいずれにおいても、そのような閾値を見つけることは難しい。より良い分離は(d) ARPLで達成可能。 

図2:ほとんどの手法は、「猫」に代表的な特徴を学習することに焦点を当てている。これに対して、「猫ではない」の潜在的な特徴を利用して「猫」を識別する。⇒ Reciprocal Point の利用。PK は潜在的な未利用のクラス外空間のインスタンス化された表現。OSRにおいて「ネコとは何か」という問題を解く際の不確実性を減らすために利用する。

図3: 開集合認識のための逆説的互変異性点学習(ARPL)提案手法の概要。(a)単一クラスに対する逆相対点学習は、既知の各クラスをその逆相対点から遠ざける。(b)多クラスAdversarialFusionは、相互点によって構成される多カテゴリ境界空間間の対立を引き起こす。その結果、既知クラスは特徴空間の周辺に押しやられ、未知クラスは境界空間内に制限される. (c)Instantiated Adversarial Enhancementは、分類器の信頼性を高めるために、より有効でより多様な紛らわしいサンプルを生成する。

MaxLogit

 MaxLogitの定義は以下の通り。

[2110.06207] Open-Set Recognition: a Good Closed-Set Classifier is All You Need? (arxiv.org)
known / unknown の AUC-ROC のみです。logit の閾値が Unknown の検出性能に大きく影響するでしょう。logit が小さいほど unknown となる定義です。

the maximum logit score (MLS) to provide our open-set score, i.e., S(y∈C|x) = maxj∈C wj · Φθ(x)

[1911.11132] Scaling Out-of-Distribution Detection for Real-World Settings (arxiv.org)
正負逆転していますので、大きいほどunknown?

This is problematic for the maximum softmax probability (MSP) baseline (Hendrycks & Gimpel, 2017), which uses the negative maximum softmax probability as the anomaly score, or − maxk exp f(x)k/ Σexp f(x)i = − maxk p(y=k|x), where f(x) is the unnormalized logits of classifier f on input x. Classifiers tend to have higher confidence on in-distribution examples than out-of-distribution examples, enabling OOD detection. 

we propose using the negative of the maximum unnormalized logit for an anomaly score − maxk f(x)k, which we call MaxLogit.

https://github.com/kkirchheim/pytorch-ood/blob/dev/src/pytorch_ood/detector/maxlogit.py 
正負逆転、negative の流儀です。

    def score(logits: Tensor) -> Tensor:
        return -logits.max(dim=1).values 

[2107.11264] Standardized Max Logits: A Simple yet Effective Approach for Identifying Unexpected Road Obstacles in Urban-Scene Segmentation (arxiv.org)
厳密には他の ML とは異なりますが、こちらも negative の流儀。

Note that we use the negative value of the final SML as the anomaly score. 

 [2311.05006] Familiarity-Based Open-Set Recognition Under Adversarial Attacks (arxiv.org)
最初の論文と同じ positive の定義です。この文献では、logit score に対する敵対的攻撃を Decrease the score of known categories と Increase the score of known categories の2種に区分しています。面白いですね。

the Maximum Logit Score (MLS) [22, 3]: SMLS(y∈F|x) := maxy fθ(x)y, which has outperformed the MSP score in prior work [22].

ARPL (Adversarial Reciprocal Point Learning) (Chen et al., 2020a; 2021)
コードを読むと、敵対的画像を用いないARPL のみの場合は MaxLogitを使用しています(+CS では SoftMaxを通しています)。最初の論文と同じ positive の定義です。実際、MNISTの例でLogit値を出力させると、inよりもoutの値が低くなります。

However,the various negative examples (unknown) are not providedfor  training  the  neural  network,  so  as  that  these  samplesobtain  lower  activation  magnitudes  from  the  neural  net-work than positive samples (known). 

MaxLogitを用いる手法では、正負に留意する必要がありそうです。


Open Set Recognition

OSR の始まりはOpenMAXからのようです。

● OpenMax (Bendale & Boult, 2016)
SoftMaxの前層の Activation Vectorを利用。
https://github.com/abhijitbendale/OSDN
https://github.com/aadeshnpn/OSDN , for Keras2.2.4 TF1.12.0

Classification-Reconstruction Learning for Open-Set Recognition (Yoshihashi et al., 2019)
日本人も頑張っているようでしたが、コードはリンク切れ。残念。

● OpenGAN (Kong & Ramanan, 2021)
Using an adversarially trained discriminator
https://github.com/aimerykong/OpenGAN, for torch
GANを利用しているのでしょうか?読んでいませんが性能は上がるようです。

● ARPL (Adversarial Reciprocal Point Learning) (Chen et al., 2020a; 2021)
https://github.com/iCGY96/ARPL, for torch1.4
上記と同じ生成系のOSR。ネットワークが3つ必要です。これは後日。

● MLS (Maximum logit score) (Vaze., et al., 2022)
OPEN-SET RECOGNITION: A GOOD CLOSED-SET CLASSIFIER IS ALL YOU NEED?
https://github.com/sgvaze/osr_closed_set_all_you_need, for torch1.9.
https://github.com/Jingkang50/OpenOOD, for torch>=1.13.1
OoDです。日本語の紹介サイトがあったですが、見当たりません。ま、要約を読んでもよくわからなかったので、文献を読んでいるわけですが。その文献を読んでも具体的な閾値の決定法は載っていません。なんらかの手法で閾値を検討する必要がでてきます。が、ネットワークの出力値を利用できる手軽な手法です。
https://github.com/sgvaze/osr_closed_set_all_you_need/issues/5
面白いのは、既知クラスの分類性能が高いほど unknown の検出(AUROC)も高くなり、相関性が見られるという点です。OoDの識別性能を鍛えると同時に分類性能が上がるので、ネットワークは一つでいいよ、ということでしょう。

known unknown

機械学習で「未知の異常を見逃したくない」といったオーダーを受けました。

その上で、「既知の異常は多クラス分類したい」ということで異常検知はダメ。少し考えて、ふと思い浮かんだのが softmax 関数の出力値をそのまま使う方法。argmax を通す前に、ある閾値以下を unkonown とする方法です。調べてみると、既に似たような方法が提案されていましたが、あまり上手い方法ではなさそうでした。

このような問題は「オープンワールド認識」の一部として機械学習の研究者が精力的に取り組まれているようです。不勉強により全く知りませんでした。一つ山を登ったと思えば、未開拓の平原が見えてきたようで焦ります。
必要性が高いにもかかわらず、あまり知られていない分野と書かれている文献がありましたので、一般的に知られていないのでしょう。

Open-Set Recognition: a Good Closed-Set Classifier is All You Need?
サブフィールドとして以下のものがあるようです。OSR と OOD検出との違いがワカラナイ。
・オープンセット認識(OSR: open set recognition)
・分布外検出(OOD検出: out-of-distribution detection)
・新規性検知(ND: novelty detection)
・異常検知(AD: anomaly detection)
・新規カテゴリ発見(novel category discovery)

また、「未知」「既知」に関する用語は、以下の4つに区別されています。KUC と UKCが ワカラナイ。GPTに聞いて埒が明かない状態です。
・ known known classes(KKC)
・ known unknown classes(KUC)
・ unknown known classes(UKC)
・ unknown unknown classes (UUC)

[2110.11334] Generalized Out-of-Distribution Detection: A Survey (arxiv.org)
こちらも5つに分類しています。
・anomaly detection (AD)
・novelty detection (ND)
・open set recognition (OSR)
・out-of-distribution (OOD) detection
・outlier detection (OD)

In safety-critical applications such as autonomous driving, the driving system must issue a warning and hand over the control to drivers when it detects unusual scenes or objects it has never seen during training

とても大事ですね。ぼーっと生きていますので、言われて初めて気づきます。


2024年4月16日火曜日

WAV + FFT

16bit 44.1kHz の wav ファイルを扱うことになりました。

スケール変換しようと思いハードウェアの資料を探しましたが見当たりません。レコーダーですので、ないのかもしれません。

2^15 で割って正規化し FFTをかけて、振幅を抽出します。で、この後が不明。ある基準値をもって dB値に変換するのですが、音圧と異なるので決まりがないようです。最大値を基準にしても良いし、最小値でも問題ないのでしょう。今回は見た目で真ん中あたりを選択しましたが、決まったやり方があれば知りたいところです。

出来上がったランニングスペクトルを見ると、現象によって奇麗に判別できました。これで全ての音声を聞かなくて済みそうです。時短に有効活用です。