まくろぐ
更新: / 作成:

多クラス分類用の F1 スコア

2 クラスの分類タスク(二値分類)の代表的な評価指標として F1 スコア がありますが、多クラスの分類タスクの評価指標としては、これを拡張した次のような指標を使います。 F1 スコアの平均をとったりするのですが、どのような単位で F1 スコアを計算するかが微妙に異なります。

評価指標説明
mean-F1レコードごとに F1 スコアを求め、それらの平均をとります。
macro-F1クラスごとに F1 スコアを求め、それらの平均をとります。
micro-F1各レコードの各クラスに対する予測(陽性 or 陰性)が TP/TN/FP/FN のいずれであるかを求め、その混同行列をもとに F1 スコアを計算します。

これらの指標は、1 つのレコードに対して複数のラベルをつけるマルチラベル分類においてよく用いられます。 下記はマルチラベル分類のタスクにおいて、各種 F1 スコアを求める実装例です。 scikit-learn の f1_score() 関数の average 引数でどのロジックを用いるかを指定できます。

scikit-learn でマルチラベル分類の F1 スコアを求める
from sklearn.metrics import f1_score

# サンプルデータ
y_true = [[0, 1, 1],  # レコード1の真のラベル (2, 3)
          [1, 1, 1]]  # レコード2の真のラベル (1, 2, 3)
y_pred = [[0, 1, 0],  # レコード1の予測されたラベル (2)
          [1, 0, 1]]  # レコード2の予測されたラベル (1, 3)

print(" mean-F1:", f1_score(y_true, y_pred, average="samples"))  # 0.733
print("macro-F1:", f1_score(y_true, y_pred, average="macro"))    # 0.777
print("micro-F1:", f1_score(y_true, y_pred, average="micro"))    # 0.750

手作業で計算してみる

それぞれのロジックをちゃんと理解するために、上記コード中のサンプルデータに関して手作業で計算してみます。

mean-F1 の計算

mean-F1 は、レコードごとに F1 値を求めてから、それらの F1 値を平均します。

  1. レコード 1 に着目して F1 値を求めます
    • 真のラベルは (2, 3)
    • 予測ラベルは (2)
    • TP=1、TN=1、FP=0、FN=1 となるので、\( F_1 = \frac{2 \cdot TP}{2 \cdot TP + FN + FP} = \frac{2 \cdot 1}{2 \cdot 1 + 1 + 0} = \frac{2}{3} \)
  2. レコード 2 に着目して F1 値を求めます
    • 真のラベルは (1, 2, 3)
    • 予測ラベルは (1, 3)
    • TP=2、TN=0、FP=0、FN=1 となるので、\( F_1 = \frac{2 \cdot TP}{2 \cdot TP + FN + FP} = \frac{2 \cdot 2}{2 \cdot 2 + 1 + 0} = \frac{4}{5} \)

上記の \( F_1 \) 値の平均をとればよいので、

$$ \operatorname{mean-F_1} = \frac{1}{2} \cdot \left( \frac{2}{3} + \frac{4}{5} \right) = \frac{11}{15} = 0.733 \cdots $$

macro-F1 の計算

macro-F1 は、クラス(ラベル)ごとに F1 値を求めてから、それらの F1 値を平均します。

  1. クラス 1 に着目して F1 値を求めます
    • TP=1、TN=1、FP=0、FN=0 なので、\( F_1 = \frac{2 \cdot TP}{2 \cdot TP + FN + FP} = \frac{2 \cdot 1}{2 \cdot 1 + 0 + 0} = \frac{2}{2} \)
  2. クラス 2 に着目して F1 値を求めます
    • TP=1、TN=0、FP=0、FN=1 なので、\( F_1 = \frac{2 \cdot TP}{2 \cdot TP + FN + FP} = \frac{2 \cdot 1}{2 \cdot 1 + 1 + 0} = \frac{2}{3} \)
  3. クラス 3 に着目して F1 値を求めます
    • TP=1、TN=0、FP=0、FN=1 なので、\( F_1 = \frac{2}{3} \) (同上)

上記の \( F_1 \) 値の平均をとればよいので、

$$ \operatorname{macro-F_1} = \frac{1}{3} \cdot \left( \frac{2}{2} + \frac{2}{3} + \frac{2}{3} \right) = \frac{7}{9} = 0.777 \cdots $$

micro-F1 の計算

micro-F1 は、各レコードの中で各クラスの予測値が TP/TN/FP/FN のいずれかであるかを判別し、それらの数をもとに \( F_1 \) を計算します。

例えば、レコード 1 のクラス 1 の予測値は陰性 (negative) つまり、レコード 1 はクラス 1 ではないと予測していますが、これは正しく陰性 (negative) と予測できているので TN (true negative) となります。 同様に、すべてのレコードとクラスの組み合わせに関して TP/TN/FP/FN のいずれかであるかを一覧にすると次のようになります。

クラス 1クラス 2クラス 3
レコード 1TNTPFN
レコード 2TPFNTP

micro-F1 は、この TP/TN/FP/FN の数を用いて \( F_1 \) 値を求めます。

$$ \operatorname{macro-F_1} = \frac{2 \cdot TP}{2 \cdot TP + FN + FP} = \frac{2 \cdot 3}{2 \cdot 3 + 2 + 0} = \frac{3}{4} = 0.75 $$

これで、手作業でも mean-F1、macro-F1、micro-F1 を求められました!

٩(๑❛ᴗ❛๑)۶ わーぃ

関連記事

更新: / 作成:

機械学習の分類タスクにおける評価指標のひとつとして balanced accuracy があります(日本語だと加重平均正答率とかかな)。 balanced accuracy は、各クラスのデータ数に偏りがある場合に正答率 (accuracy) の計算に補正を加えます。

balanced accuracy の計算方法

通常の正解率 (accuracy) の計算は次のようなシンプルなものです。

$$ \operatorname{accuracy} = \frac{正解数 (r)}{データ数 (n)} $$

例えば、10 個のデータのうち 8 個の予測に成功した場合は、accuracy は 0.8 (80%) になりますが、blanced accuracy の場合は、各クラスに属するデータの数の逆数を重みとした加重平均を取ります。

$$ \operatorname{balanced accuracy} = \frac{1}{N} \sum_{i=1}^{N} \frac{r_i}{n_i} $$

  • \( N \) … クラス数
  • \( r_i \) … クラス \( i \) に属すると正しく予測できたデータ数
  • \( n_i \) … クラス \( i \) の(実際の)データ数

要するに、もともとたくさんのデータがあるクラスに属すると予測して正解したとしても、accuracy はあまり上がらないようにするということです。 逆に、少ししかデータがないクラスに属すると予測して正解すれば、accuracy は大きく上がります。 感覚としては、各クラスごとに個別に accuracy を求めてから平均するという感じです。

balanced accuracy の例

例として、7 個のデータを 3 クラスに分類する問題を考えてみます。

/p/g6v9puz/img-001.drawio.svg
図: blanced accuracy の例題

クラス 1 に属すると予測したデータの内 2 個が正解、クラス 2 に属すると予測したデータの内 1 個が正解だった場合の計算例です。

$$ \begin{align} \operatorname{balanced accuracy} &= \frac{1}{N} \sum_{i=1}^{N} \frac{r_i}{n_i} \\ &= \frac{1}{3} \left( \frac{2}{4} + \frac{1}{1} + \frac{0}{2} \right) \\ &= 0.5 \text{ (50%)} \end{align} $$

実際に分類確率を出力するモデルを使ってクラス分類を行う場合は、このデータ数の重み \( 1/n \) を加味した上で、どのクラスに分類するかを判断します。 例えば、モデルの出力として、クラス 1 の確率が 0.3、クラス 3 の確率が 0.2 という値が得られたとします。 このとき、単純にこの確率 \( (0.3 \gt 0.2) \) だけを見てクラス 1 に属するデータであると予測するのではなく、データ数の重みで補正した \( 0.3 \times \frac{1}{4} = 0.075 \)、\( 0.2 \times \frac{1}{2} = 0.1 \) という値を使って、クラス 3 に属すると予測します。

参考

関連記事

更新: / 作成:

プロファイルとは

PowerShell は起動時に $PROFILE のパスに格納されたプロファイルファイルを読み込むようになっています。 このファイルで関数の定義や初期化処理を行うことで、PowerShell を便利に使えるようになります。 $PROFILE には次のようなパスが格納されています。

PS C:\> $profile
C:\Users\maku\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

プロファイルの作成

デフォルトでは $PROFILE が示すファイルは存在しない可能性があるので、New-Item コマンドレットなどを使って、エディタで開く前にファイルを生成しておく必要があります。

プロファイルを作成してエディタで開く
New-Item -Path $profile -ItemType file -Force
notepad $profile

このファイルを作成したあとに新しく PowerShell を開こうとすると、実行ポリシー 関連のセキュリティエラーが発生します。 これは、デフォルトで ps1 ファイルの実行が許可されていないからです。

セキュリティエラー
. : ファイル C:\Users\maku\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 を読み込めません。
ファイル C:\Users\maku\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 はデジタル署名されていません。
このスクリプトは現在のシステムでは実行できません。
スクリプトの実行および実行ポリシーの設定の詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。

現在の実行ポリシーの一覧は、Get-ExecutionPolicy コマンドレットで確認できます。

PS C:\> Get-ExecutionPolicy -List

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine       AllSigned

カレントユーザーによるスクリプトの実行を許可するには、次のように Set-ExecutionPolicy コマンドレットを実行します。

PS C:\> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

ここで指定している RemoteSigned ポリシーは、「インターネット上の署名されたスクリプト」および「ローカルコンピューター上のスクリプト」の実行を許可するポリシーです。

プロファイルの設定例

ディレクトリ移動用のコマンドを定義

下記は、ディレクトリ移動のための関数(cd-gitworku)を定義する例です。 ついでに PowerShell の起動時にその関数を呼び出して、ディレクトリを移動しています。 よく使う作業ディレクトリに自動的に移動するようにしておくと便利です(Windows ターミナルの設定でも初期ディレクトリは設定できますが)。

Microsoft.PowerShell_profile.ps1
Function cd-gitwork {
  cd D:\y\gitwork  # Set-Location -Path D:\y\gitwork でも OK
}
Function u { cd ..  }
Function uu { cd ..\..  }
Function uuu { cd ..\..\..  }

# PowerShell 起動時にディレクトリを移動
cd-gitwork

独自コマンドの定義方法としては、Set-Alias コマンドレットによるエイリアス定義もありますが、Set-Alias は柔軟なパラメーター設定ができないので、Function を使って関数として定義するのがよいです。

他のスクリプトを読み込む

複数の PC で設定を共有したいときは、Dropbox などに共通スクリプトを置いておいて、. で読み込むようにします。 各 PC のプロファイル ($profile) には、次のような 1 行だけを記述しておきます。

Microsoft.PowerShell_profile.ps1
. D:\Dropbox\share\config\powershell\profile.ps1

関連記事

メニュー

まくろぐ
サイトマップまくへのメッセージ