機械学習において、トレーニングおよび検証メトリック グラフから何がわかるでしょうか?

機械学習において、トレーニングおよび検証メトリック グラフから何がわかるでしょうか?

この記事では、トレーニングと検証の考えられる状況をまとめ、これらのチャートがどのような情報を提供できるかを紹介します。

簡単なコードから始めましょう。次のコードは、トレーニング プロセスの基本的なフレームワークを設定します。

 sklearn.model_selection から train_test_split をインポートします
sklearn.datasets から make_classification をインポートします
輸入トーチ
torch.utils.data から Dataset、DataLoader をインポートします
torch.optim を torch_optim としてインポートします。
torch.nnをnnとしてインポートする
torch.nn.function を F としてインポートします。
numpyをnpとしてインポートする
matplotlib.pyplot を pltclass MyCustomDataset(Dataset) としてインポートします。
def __init__(self, X, Y, スケール=False):
自己.X = torch.from_numpy(X.astype(np.float32))
自己.y = torch.from_numpy(Y.astype(np.int64))

__len__(自分)を定義します:
len(self.y) を返す

__getitem__(self, idx)を定義します。
self.X[idx]、self.y[idx]を返します。def get_optimizer(model、lr=0.001、wd=0.0):
パラメータ = フィルター(lambda p: p.requires_grad, model.parameters())
optim = torch_optim.Adam(パラメータ、lr=lr、weight_decay=wd)
optimdef train_model(model, optim, train_dl, loss_func) を返します:
# モデルがトレーニングモードになっていることを確認する
モデル.train()
合計 = 0
合計損失 = 0
train_dlのx、yについて:
バッチ = y.shape[0]
# このバッチ分のデータに対してモデルをトレーニングする
ロジット = モデル(x)
# 損失関数を実行します。これはトレーニングループを呼び出すときに決定します。
損失 = loss_func(logits, y)
# 次の3行はPyTorchのバックプロパゲーションの優れた機能をすべて実行します
最適化ゼロ勾配()
損失.後方()
最適化ステップ()
# このエポックのサンプルの総数を継続的にチェックする
合計 += バッチ
# そして損失の合計を記録しておく
sum_loss += バッチ*(loss.item())
sum_loss/totalを返す
def train_loop(モデル、train_dl、valid_dl、エポック、loss_func、lr=0.1、wd=0):
optim = get_optimizer(モデル、lr=lr、wd=wd)
トレーニング損失リスト = []
val_loss_list = []
acc_list = []
i が範囲(エポック)内である場合:
損失 = train_model(モデル、最適化、train_dl、損失関数)
# このエポックをトレーニングした後、進捗状況のリストを保持します
# 各時代の損失
train_loss_list.append(損失)
val、acc = val_loss(モデル、valid_dl、loss_func)
# 検証損失と精度についても同様
val_loss_list.append(val)
acc_list.append(acc)
print("トレーニング損失: %.5f 有効な損失: %.5f 精度: %.5f" % (loss, val, acc))

train_loss_list、val_loss_list、acc_list を返す
val_loss(モデル、valid_dl、loss_func):
# モデルをトレーニングモードではなく評価モードにする
モデル評価()
合計 = 0
合計損失 = 0
正解 = 0
バッチカウント = 0
valid_dl の x、y について:
バッチカウント += 1
現在のバッチサイズ = y.shape[0]
ロジット = モデル(x)
損失 = loss_func(logits, y)
合計損失 += 現在のバッチサイズ*(損失.item())
合計 += 現在のバッチサイズ
# 上記のコードはすべて本質的には同じであり、
# トレーニングなのでコメントを見てください
# 返された予測のうちどれが最も大きな声で聞こえるか調べる
# すべて、そしてそれが私たちの予測です
preds = logits.sigmoid().argmax(1)
# 私たちの予測が正しいかどうか見てみましょう
正解 += (予測値 == y).float().mean().item()
sum_loss/total、correct/batch_count を返す
def view_results(train_loss_list、val_loss_list、acc_list):
plt.rcParams["figure.figsize"] = (15, 5)
plt.figure()
エポック = np.arange(0, len(train_loss_list)) plt.subplot(1, 2, 1)
plt.plot(エポック-0.5、train_loss_list)
plt.plot(エポック、val_loss_list)
plt.title('モデル損失')
plt.ylabel('損失')
plt.xlabel('エポック')
plt.legend(['train', 'val', 'acc'], loc = '左上')

plt.サブプロット(1, 2, 2)
plt.plot(acc_list)
plt.title('精度')
plt.ylabel('精度')
plt.xlabel('エポック')
plt.legend(['train', 'val', 'acc'], loc = '左上')
plt.show()

def get_data_train_and_show(モデル、batch_size=128、n_samples=10000、n_classes=2、n_features=30、val_size=0.2、epochs=20、lr=0.1、wd=0、break_it=False):
# 関連するすべてのデータが揃っていると仮定して、架空のデータセットを作成します。
# EDA / 機能エンジニアリングが完了し、これが私たちの
# 結果データ
X、y = make_classification(n_samples=n_samples、n_classes=n_classes、n_features=n_features、n_informative=n_features、n_redundant=0、random_state=1972)

if break_it: # 具体的にデータを壊す
X = np.random.rand(n_samples,n_features)
X_train、X_val、y_train、y_val = train_test_split(X、y、test_size=val_size、random_state=1972) train_ds = MyCustomDataset(X_train、y_train)
valid_ds = MyCustomDataset(X_val, y_val)
train_dl = DataLoader(train_ds、batch_size=batch_size、shuffle=True)
valid_dl = DataLoader(valid_ds、batch_size=batch_size、shuffle=True) train_loss_list、val_loss_list、acc_list = train_loop(model、train_dl、valid_dl、epochs=epochs、loss_func=F.cross_entropy、lr=lr、wd=wd)
結果を表示(train_loss_list、val_loss_list、acc_list)

上記のコードは非常にシンプルです。データの取得、トレーニング、検証という基本的なプロセスです。それでは本題に入りましょう。

シナリオ 1 - モデルは学習しているように見えるが、検証や精度のパフォーマンスが低い

ハイパーパラメータに関係なく、モデルのトレーニング損失はゆっくりと減少しますが、値損失は減少せず、精度は何かを学習していることを示しません。

たとえば、この場合、バイナリ分類の精度は約 50% になります。

クラス Scenario_1_Model_1(nn.Module):
def __init__(self, in_features=30, out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, out_features)
def forward(self, x):
x = 自己.lin1(x)
xを返す
get_data_train_and_show(シナリオ1モデル1()、lr=0.001、break_it=True)

データには「学習」を可能にするのに十分な情報がありません。トレーニング データには、モデルが「学習」するのに十分な情報が含まれていない可能性があります。

この場合(コード内のトレーニング データはランダムです)、実質的なことは何も学習できないことを意味します。

データには、そこから学習するのに十分な情報が含まれている必要があります。 EDA と機能エンジニアリングが鍵です! モデルは、存在しないものを作り出すのではなく、学習可能なものを学習します。

シナリオ2 - トレーニング、検証、精度曲線はすべて非常に不安定です

たとえば、次のコード: lr=0.1, bs=128

クラス Scenario_2_Model_1(nn.Module):
def __init__(self、in_features=30、out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, out_features)
def forward(self, x):
x = 自己.lin1(x)
xを返す
get_data_train_and_show(シナリオ2モデル1()、lr=0.1)

「学習率が高すぎる」または「バッチ サイズが小さすぎる」学習率を 0.1 から 0.001 に下げてみてください。これにより、「跳ね返る」ことはなく、スムーズに減少します。

 get_data_train_and_show(シナリオ1モデル1()、lr=0.001)

学習率を下げるだけでなく、バ​​ッチ サイズを増やすと、よりスムーズになります。

 get_data_train_and_show(シナリオ1_モデル1()、lr=0.001、バッチサイズ=256)

シナリオ3 - トレーニング損失はゼロに近く、精度は良好だが、検証は低下していないが、増加している

クラス Scenario_3_Model_1(nn.Module):
def __init__(self、in_features=30、out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, 50)
自己.lin2 = nn.Linear(50, 150)
自己.lin3 = nn.Linear(150, 50)
self.lin4 = nn.Linear(50, out_features)
def forward(self, x):
x = F.relu(self.lin1(x))
x = F.relu(self.lin2(x))
x = F.relu(self.lin3(x))
x = 自己.lin4(x)
xを返す
get_data_train_and_show(シナリオ3_モデル1()、lr=0.001)

これは明らかに過剰適合です。トレーニング損失は低く、精度は高いですが、検証損失とトレーニング損失はどんどん大きくなっており、これは典型的な過剰適合の指標です。

基本的に、モデルの学習があまりにもうまくいっています。 トレーニング データを非常によく記憶しているため、新しいデータに一般化することもできません。

最初に試せるのは、モデルの複雑さを軽減することです。

クラス Scenario_3_Model_2(nn.Module):
def __init__(self, in_features=30, out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, 50)
self.lin2 = nn.Linear(50, out_features)
def forward(self, x):
x = F.relu(self.lin1(x))
x = 自己.lin2(x)
xを返す
get_data_train_and_show(シナリオ3_モデル2()、lr=0.001)

これにより、モデルはより良くなりますが、L2 重み減衰正規化を導入して、さらにモデルを良くすることもできます (より浅いモデルの場合)。

 get_data_train_and_show(シナリオ3_モデル2()、lr=0.001、wd=0.02)

モデルの深さとサイズを維持したい場合は、ドロップアウト (より深いモデルに適しています) の使用を試すことができます。

クラス Scenario_3_Model_3(nn.Module):
def __init__(self, in_features=30, out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, 50)
自己.lin2 = nn.Linear(50, 150)
自己.lin3 = nn.Linear(150, 50)
self.lin4 = nn.Linear(50, out_features)
自己.ドロップ = nn.ドロップアウト(0.4)
def forward(self, x):
x = F.relu(self.lin1(x))
x = 自己ドロップ(x)
x = F.relu(self.lin2(x))
x = 自己ドロップ(x)
x = F.relu(self.lin3(x))
x = 自己ドロップ(x)
x = 自己.lin4(x)
xを返す
get_data_train_and_show(シナリオ3_モデル3()、lr=0.001)

シナリオ4 - トレーニングと検証はうまくいったが、精度は向上しなかった

lr = 0.001、bs = 128(デフォルト、分類カテゴリ = 5

クラス Scenario_4_Model_1(nn.Module):
def __init__(self, in_features=30, out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, 2)
self.lin2 = nn.Linear(2, out_features)
def forward(self, x):
x = F.relu(self.lin1(x))
x = 自己.lin2(x)
xを返す
get_data_train_and_show(シナリオ4モデル1(出力機能=5)、lr=0.001、n_classes=5)

学習能力が不十分です: モデル内のレイヤーの 1 つに、モデルの可能な出力のクラス数よりも少ないパラメータがあります。 この場合、出力クラスは 5 つありますが、中央のパラメーターは 2 つだけです。

これは、モデルを埋めるために情報をより小さなレイヤーに通す必要があるため情報が失われ、レイヤーのパラメータが再び拡大されるとこの情報を回復することが困難になることを意味します。

したがって、記録層のパラメータはモデルの出力サイズよりも小さくなってはなりません。

クラス Scenario_4_Model_2(nn.Module):
def __init__(self、in_features=30、out_features=2):
スーパー().__init__()
self.lin1 = nn.Linear(in_features, 50)
self.lin2 = nn.Linear(50, out_features)
def forward(self, x):
x = F.relu(self.lin1(x))
x = 自己.lin2(x)
xを返す
get_data_train_and_show(シナリオ4モデル2(出力機能=5)、lr=0.001、n_classes=5)

要約する

上記は、トレーニングおよび検証中の曲線の一般的な例です。同じ状況に遭遇したときに、すぐに見つけて改善できることを願っています。


<<:  欧州のAI法案がまもなく導入され、世界の技術規制に影響を及ぼす可能性がある

>>:  AIは脳スキャンだけであなたの政治的思想を予測できる

ブログ    

推薦する

...

AI搭載のレンガ積みロボットが建設業界に革命を起こす

現在、建設部門は大規模なプロジェクトによって活性化しており、大きな成長を牽引しています。しかし、これ...

2020 年に AI テクノロジーはどのような変化をもたらすでしょうか?

近年、人工知能は頻繁に話題になっていますが、まだ真の実現には程遠い状況です。人工知能技術の開発におけ...

ファーウェイが推進する「マシンビジョン」はインダストリー4.0成功の鍵となるのか?

最近、「新インフラ」や「デジタルインフラ」がホットワードとなっている。新インフラの一つである「産業イ...

RPAと医療におけるインテリジェントオートメーションの台頭

デジタル変革はヘルスケアにおける大きなトレンドと考えられており、インテリジェントな自動化もその一部と...

...

コードはオープンソースです!非常に役立つ「機械学習実践ガイド」の第2版がついに登場

昨年の今頃、Red Stone は機械学習の非常に優れた実践ガイドブック「Hands-On Mach...

...

AI が大学入試のエッセイのテーマを予測: 科学、形而上学、それとも誇大広告?

大学受験生にとって、出題される問題を全て知っていて、分からない問題の答えを暗記していることが一番幸せ...

Testin Cloud Testing: テクノロジーを活用して企業の飛躍を支援

急速に発展するデジタル時代において、ビジネスの成功にとって高品質で効率的なテスト サービスが重要であ...

上海に初のAI野菜市場が上陸。Alipayスキャンコード登録により、手をスワイプしてコードをスキャンするだけでドアが開く

[[250311]] 「顔スキャン」ではなく「手のひらスキャン」で、あなたの家のすぐそばに「AI野菜...

...

自分のIQに挑戦してみませんか? 10 種類の機械学習アルゴリズムを理解してデータ サイエンティストになろう

データ サイエンティストになりたいですか? 十分な知識と新しいことに対する好奇心が必要です。このため...