PyTorch を使用して複数分類の問題を解決する方法を教える

この記事は、 Xiaomantou Learning Python によるHuawei クラウド コミュニティ「PyTorch を使用して複数分類の問題を解決する: ディープ ラーニング モデルの構築、トレーニング、および評価」から共有されたものです。

導入

PyTorch は、複数分類の問題を扱う場合に非常に便利な深層学習フレームワークです。このブログでは、PyTorch を使用して複数分類の問題を解決する方法について説明します。多分類問題の基本概念を紹介し、シンプルな多分類ニューラル ネットワーク モデルを構築し、データの準備方法、モデルのトレーニング方法、および結果の評価方法を示します。

多分類問題とは何ですか?

多分類問題は、入力データを複数の異なるカテゴリまたはラベルに分類することを目的とする機械学習タスクです。二値分類問題とは異なり、多分類問題には 3 つ以上のカテゴリの分類タスクが含まれます。たとえば、画像分類問題では、画像を猫、犬、鳥などのさまざまなカテゴリに分類できます。

処理手順

  • データを準備します:

データセットを収集して準備し、各サンプルに、それが属するカテゴリを示す対応するラベルが付けられていることを確認します。

モデルのトレーニング、チューニング、パフォーマンス評価のために、データ セットをトレーニング セット、検証セット、テスト セットに分割します。

  • データの前処理:

    正規化、標準化、欠損値処理、データ拡張などのデータを前処理して、モデル トレーニングの安定性とパフォーマンスを確保します。

  • モデル アーキテクチャを選択します。

    問題の性質に応じて、適切な深層学習モデル アーキテクチャを選択します。これには通常、畳み込みニューラル ネットワーク (CNN)、リカレント ニューラル ネットワーク (RNN)、Transformer などが含まれます。

  • 損失関数を定義します。

    多分類問題に適切な損失関数 (通常はクロスエントロピー損失) を選択します。

  • オプティマイザーを選択します。

    確率的勾配降下法 (SGD)、Adam、RMSprop などの適切な最適化アルゴリズムを選択して、モデルをトレーニングし、重みを調整します。

  • トレーニングモデル:

    トレーニング データ セットを使用してモデルをトレーニングします。各トレーニング反復では、損失関数の値を減らすために、順伝播および逆伝播を通じてモデル パラメーターが更新されます。

  • 評価モデル:

    検証セットを使用してモデルのパフォーマンスを評価します。一般的なパフォーマンス指標には、精度、精度、再現率、F1 スコアなどが含まれます。

  • モデルのチューニング:

    検証セットのパフォーマンスに基づいて、さまざまなハイパーパラメーター設定、モデル アーキテクチャの変更、またはデータ拡張戦略を試してモデルを調整できます。

  • テストモデル:

    最後に、モデルのパフォーマンスが独立したテスト データセットで評価され、最終的なパフォーマンス推定値が得られます。

  • 導入モデル:

    トレーニングされたモデルを実際のアプリケーションにデプロイして、複数分類タスクをリアルタイムまたはバッチ処理します。

多分類問題

前に説明した問題のほとんどは 2 クラス分類です。2 クラス分類問題の場合、p(0) が求まれば、p(1)=1-p(0) は比較的簡単ですが、このセクションでは多分類を導入すると、得られるものは p(i)(i=1,2,3,4...) に変換され、上記の各確率が 0 より大きいこと、および合計が満たされる必要があります。は1です。

複数分類の問題に対処するために、ここでは Softmax Layer と呼ばれる新しい層を導入します。

cke_138.png

次に、Softmax Layer レイヤーについて説明します。

cke_14911.png

まず、e の zi 乗を計算するための指数を計算します。理由は非常に簡単です。e の指数関数は常に 0 より大きく、分母は e の z1 乗 + e の z2 乗 + e の z3 乗です。 e...合計すると、すべての確率を合計すると 1 になります。

下の図はソフトマックスを鮮やかに示しています。ここでの指数はインデックスを指します。上で述べたように、最初に指数を見つけて分子を取得し、次にすべての指数を合計し、最後に 1 つずつ除算して各確率を取得します。

cke_140.png

次に損失関数を見てみましょう

cke_141.png

Liu Er のコードに従って numpy を使用して実装する場合は、次のように実装できます。

numpyをnpとしてインポート

y = np.array([1,0,0])

z = np.array([0.2,0.1,-0.1])

y_pred = np.exp(z)/np.exp(z).sum()

loss = (-y * np.log(y_pred)).sum()

印刷(ロス)

実行結果は以下の通りです

cke_142.png

注: ニューラル ネットワークの最後の層をアクティブにする必要はありません。

パイトーチで

輸入トーチ

y = torch.LongTensor([0]) # 長整数

z = torch.Tensor([[0.2, 0.1, -0.1]])

基準 = torch.nn.CrossEntropyLoss()

損失 = 基準(z, y)

印刷(ロス)

実行結果は以下の通りです

cke_143.png

以下は例に基づいたデモンストレーションです

基準 = torch.nn.CrossEntropyLoss()

Y = torch.LongTensor([2,0,1])

Y_pred1 = torch.Tensor([[0.1, 0.2, 0.9],

[1.1、0.1、0.2]、

[0.2、2.1、0.1]])

Y_pred2 = torch.Tensor([[0.8, 0.2, 0.3],

[0.2、0.3、0.5]、

[0.2、0.2、0.5]])

l1 = 基準(Y_pred1, Y)

l2 = 基準(Y_pred2, Y)

print("バッチ損失1 = ", l1.data, "\nバッチ損失2=", l2.data)

実行結果は以下の通りです

cke_144.png

上記のコードによれば、最初の損失は 2 番目の損失よりも小さいことがわかります。理由は非常に単純で、Y_pred1 の各予測分類は Y と一致していると思いますが、Y_pred2 は若干異なるため、当然損失が大きくなります。

MNIST データセットの実装

最初のステップはパッケージをガイドすることです

輸入トーチ

torchvision インポート変換から

torchvision インポート データセットから

torch.utils.data から DataLoader をインポート

torch.nn.functionをFとしてインポート

torch.optim を optim としてインポートします

次はデータの準備です

バッチサイズ = 64

#transform で 0-1 に変換でき、形状変換は 28×28 から 1×28×28 になります。

変換 = 変換.Compose([

変換.ToTensor()、

transforms.Normalize((0.1307, ), (0.3081, )) # 平均値と標準偏差 std

])

train_dataset = datasets.MNIST(root='../dataset/mnist/',

電車=本当、

ダウンロード=真、

変換=変換)

train_loader = DataLoader(train_dataset,

シャッフル=真、

バッチサイズ=バッチサイズ)

test_dataset = datasets.MNIST(root='../dataset/mnist/',

train=False、

ダウンロード=真、

変換=変換)

test_loader = DataLoader(test_dataset,

シャッフル=偽、

バッチサイズ=バッチサイズ)

cke_29794.png

次にネットワークを構築します

クラスネット(torch.nn.Module):

def __init__(自分自身):

super(Net, self).__init__()

self.l1 = torch.nn.Linear(784, 512)

self.l2 = torch.nn.Linear(512, 256)

self.l3 = torch.nn.Linear(256, 128)

self.l4 = torch.nn.Linear(128, 64)

self.l5 = torch.nn.Linear(64, 10)

def forward(self, x):

x = x.view(-1, 784)

x = F.relu(self.l1(x))

x = F.relu(self.l2(x))

x = F.relu(self.l3(x))

x = F.relu(self.l4(x))

return self.l5(x) # 最後の層はアクティブ化されていないことに注意してください

モデル = ネット()

次に、損失とオプティマイザを定義します。

基準 = torch.nn.CrossEntropyLoss()

optimizer = optim.SGD(model.parameters()、lr=0.01、momentum=0.5)

次はトレーニングです

デフォルトトレイン(エポック):

ランニングロス = 0.0

バッチ_idx の場合、enumerate(train_loader, 0) のデータ:

入力、ターゲット = データ

オプティマイザー.zero_grad()

# 前方 + 逆方向 + 更新

出力 = モデル(入力)

損失 = 基準(出力、目標)

loss.backward()

オプティマイザー.ステップ()

running_loss += loss.item()

バッチ IDx % 300 == 299 の場合:

print('[%d, %5d] 損失: %.3f' % (エポック + 1、batch_idx + 1、running_loss / 300))

ランニングロス = 0.0

デフォルトテスト():

正解 = 0

合計 = 0

with torch.no_grad(): # これにより、埋め込みコードがグラデーションを実行しないのを防ぎます

test_loader 内のデータの場合:

画像、ラベル = データ

出力 = モデル(画像)

_、予測 = torch.max(outputs.data, dim=1)

合計 += ラベル.サイズ(0)

正しい += (予測された == ラベル).sum().item()

print('テスト セットの精度: %d %%' % (100 * 正解 / 合計))

最後に実行を呼び出します

__name__ == '__main__'の場合:

range(10) 内のエポックの場合:

列車(時代)

テスト()

NLLLoss と CrossEntropyLoss

NLLLoss と CrossEntropyLoss (クロスエントロピー損失とも呼ばれる) は、深層学習で一般的に使用される 2 つの損失関数であり、通常は分類タスクで、モデルの出力と真のラベルの間のギャップを測定するために使用されます。これらにはいくつかの類似点もありますが、いくつかの相違点もあります。

同じ点:

目的: どちらも分類タスクで使用され、モデルのトレーニングと最適化のためにモデルの出力と真のラベルの間の差異を評価します。

数学的根拠: NLLLoss と CrossEntropyLoss は本質的にクロスエントロピー損失の異なる変種であり、どちらも情報理論の概念に基づいており、2 つの確率分布間の類似性を測定します。

入力形式: 通常、モデルの出力は、各クラスの予測確率と真のラベルを表す確率分布であると期待されます。

違い:

入力形式: NLLLoss は通常、入力が対数確率であることを期待しますが、CrossEntropyLoss は通常、入力が非対数確率であることを期待します。実際のアプリケーションでは、CrossEntropyLoss は通常、元のモデル出力を確率分布に変換するためにソフトマックス演算と組み合わせて使用​​されますが、NLLLoss は対数確率を直接使用できます。

対数化: NLLLoss では、対数確率を取得するためにモデル出力の確率が対数的である (対数を取る) 必要があり、それを実ラベルの離散確率分布と比較します。CrossEntropyLoss は通常、非対数確率値を真のラベルと比較するためにソフトマックス演算の直後に使用されます。

出力次元: NLLLoss はより汎用的で、マルチクラス分類やシーケンス生成などのタスクを含むさまざまな状況で使用できるため、より高い柔軟性が必要です。CrossEntropyLoss は、通常、複数カテゴリの分類タスクに使用されます。

要約すると、NLLLoss と CrossEntropyLoss は両方とも分類タスクに使用されますが、入力形式と使用法にいくつかの違いがあります。一般に、どの損失関数を選択するかは、モデル出力の形式とタスクの性質によって異なります。モデル出力がすでに対数確率形式である場合は、通常 NLLLoss が使用され、そうでない場合は通常、CrossEntropyLoss が使用されます

クリックしてフォローし、できるだけ早くHuawei Cloudの新しいテクノロジーについて学びましょう~

Microsoft、新しい「Windowsアプリ」を発表 Xiaomi、Xiaomi Velaが完全オープンソース、基盤となるカーネルはNuttX Vite 5 であることを正式発表 Alibaba Cloud 11.12が正式リリース 障害の原因が判明:アクセスキーサービス(アクセスキー)の異常 GitHub レポート: TypeScript が Java に代わって 3 番目に人気になる 言語オペレータの奇跡的な操作 : バックグラウンドでネットワークを切断し、ブロードバンド アカウントを無効にし、ユーザーに光モデムの変更を強制する ByteDance: AI を使用して Linux カーネル パラメータを自動的に調整する Microsoft オープン ソースTerminal Chat Spring Framework 6.1 が正式に GA OpenAI の元 CEO 兼社長の Sam Altman 氏と Greg Brockman 氏が Microsoft に入社
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4526289/blog/10149844