pytorchの基本(2)

pytorchの基本(2つ)

活性化関数

pytorchのアクティベーション機能はnnモジュールにあります!

import torch
from torch import nn
tanh = nn.Tanh()

x = torch.tensor([1, 2, 3, 4], dtype=float)
tanh = nn.Tanh()
y = tanh(x)
print(y)
结果:
tensor([0.7616, 0.9640, 0.9951, 0.9993], dtype=torch.float64)

ReLu、Sigmoidなどはすべてnnであり、対応する関数はそれらを直接呼び出すことで取得できます。

SoftMax

import torch
from torch import nn

softmax = nn.Softmax(dim=1)

例:softmax(x)、xは、shape =(64、10)のデータです。10が配置されている次元である最初の次元でsoftmaxを実行します。つまり、グループとして10個のデータに対してsoftmax操作を実行します。

[[x0,x1,x2,x3,x4,x5,x6,x7,x8,x9],
 [x0,x1,x2,x3,x4,x5,x6,x7,x8,x9],
 ...x61
 [x0,x1,x2,x3,x4,x5,x6,x7,x8,x9]]

64ここにバッチサイズがあります!

別の例では、データバッチサイズは1です。つまり、サンプルが1つしかない場合は、次のようになります。

import torch
from torch import nn

x = torch.tensor([1, 2, 3, 4], dtype=float)
# 默认dim就是0,这里写不写都可以
sofrmax = nn.Softmax(dim=0)
y = softmax(x)

DataLoader

DataLoaderのデータセットは、リスト、テンソル(反復可能なタイプである限り)にすることができ、DataLoaderをトラバースするためにすべての要素を取得できます。

from torch.utils.data import DataLoader

x = torch.tensor([1, 2, 3, 4, 5, 6])
# 将y根据x编程独热向量,tolist是为了将y整个可以变成tensor类型(因为如果list中元素为tensor是变不成tensor类型的)
y = [torch.zeros((6,)).tolist() for i in x]
y = torch.tensor(y)
# 将x,y放到一个dataset中,以便转换成DataLoader后可以方便的取出数据
dataset = []
for i in range(len(x)):
    # 转成独热向量
    y[i][x[i]-1] = 1.0
    # 将x,y对用元素变成元组,放到dataset中[(x0,y0),(x1,y1)...]
    dataset.append((x[i], y[i]))
print(y)
print(dataset)
print()
    
batch_size = 2
train_loader = DataLoader(dataset=dataset,
                         batch_size=batch_size,
                         shuffle=True)
for x, y in train_loader:
    print("x:", x)
    print("y:", y)
结果:
tensor([[1., 0., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0., 0.],
        [0., 0., 1., 0., 0., 0.],
        [0., 0., 0., 1., 0., 0.],
        [0., 0., 0., 0., 1., 0.],
        [0., 0., 0., 0., 0., 1.]])
[(tensor(1), tensor([1., 0., 0., 0., 0., 0.])), (tensor(2), tensor([0., 1., 0., 0., 0., 0.])), (tensor(3), tensor([0., 0., 1., 0., 0., 0.])), (tensor(4), tensor([0., 0., 0., 1., 0., 0.])), (tensor(5), tensor([0., 0., 0., 0., 1., 0.])), (tensor(6), tensor([0., 0., 0., 0., 0., 1.]))]

x: tensor([4, 2])
y: tensor([[0., 0., 0., 1., 0., 0.],
        [0., 1., 0., 0., 0., 0.]])
x: tensor([5, 1])
y: tensor([[0., 0., 0., 0., 1., 0.],
        [1., 0., 0., 0., 0., 0.]])
x: tensor([3, 6])
y: tensor([[0., 0., 1., 0., 0., 0.],
        [0., 0., 0., 0., 0., 1.]])

ワンホットエンコーディング(散布補間を使用)

上記のワンホットエンコーディングを作成することに加えて、テンソルが提供するワンホットエンコーディングの散布方法を使用することもできます。

# 这是一个batch为6,共有6类的一个分类任务
label = torch.tensor([1, 2, 3, 4, 5, 6])
# 变成二维标签,[[1], [2], ..., [6]]
label = label.reshape(-1, 1)

# tensor.scatter(dim, index, src)
# dim: 对哪个维度进行插入
# index: 对哪个位置插值
# src: 插得值是啥
one_hot = torch.zeros(label.shape[0], 6).scatter(1, label-1, 1)
# zeros得到的是一个shape=(6, 6)的一个全0 tensor
# 对这个tensor进行插值,对1维、每行插得位置分别对应label-1中的每个元素,插得值为1
结果:
tensor([[1., 0., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0., 0.],
        [0., 0., 1., 0., 0., 0.],
        [0., 0., 0., 1., 0., 0.],
        [0., 0., 0., 0., 1., 0.],
        [0., 0., 0., 0., 0., 1.]])

わからない場合は、サンプルを使用して次のことを行います。

label = torch.tensor([1])

one_hot = torch.zeros(6).scatter(0, label-1, 1)
结果:
tensor([1., 0., 0., 0., 0., 0.])

脱落

import torch
from torch import nn

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        # 隐藏层有500个节点,接收输入为784大小的数据
        self.hidden = nn.Linear(784, 500)
        # 将输入的数据50%变为0,也就变相的让向它提供数据的那一层丢弃50%的节点。
        self.drop = nn.Dropout(p=0.5)
        # 10个分类
        self.out = nn.Linear(500, 10)
        
    def forward(self, x):
        x = self.hidden(x)
        x = self.drop(x)
        y_hat = self.out(x)
        return y_hat

重量減衰

重みの減衰はトレーナーに配置されます(損失関数ではありません)。バックプロパゲーション時に古い損失関数を引き続き使用するため、勾配降下法がパラメーターを更新するときに更新メソッドに逆数の正則化項を追加し(ステップ)、パラメーターを直接取り込むことで重みの減衰を実現できます。

import torch
from torch import nn, optim
optimizer = optim.SGD(model.parameters(), lr, weight_decay=0.1)
  • weight_decayは、正則化項のパラメーターです。(モデルのハイパーパラメーターである正則化項の重要性を判断します)

オプティマイザ

すべてのオプティマイザーの本質は最急降下法です!

SGD

SGDは基本的なアルゴリズムです。

  • 短所:鞍点で下げることはできません(最悪の場合、実際に遭遇することは基本的に不可能です)

ここに画像の説明を挿入

勢い

最急降下法の慣性を作成します。

  • 利点:高速収束
  • 短所:トレーニング回数が少ないと方向が正しくない場合がありますが(収束が速いため、方向を探すときにブレーキがかかりにくい)、トレーニング回数が多いと方向が正しくなりません。正しい方向に戻すように調整する

NAG

これは、Momentumの改良されたアルゴリズムです。

  • 利点:勢いよりも正しい方向を見つけるのが速い
  • 短所:トレーニングセッションの数が少ない場合でも、方向は正しくありません

アダム

確率的勾配降下法は、すべての重みを更新するために単一の学習率(つまり、アルファ)を​​維持し、学習率はトレーニングプロセス中に変化しません。また、Adamは、勾配の1次モーメント推定と2次モーメント推定を計算することにより、さまざまなパラメーターに対して独立した適応学習率Adamアルゴリズムを設計します。(つまり、Adam最適化アルゴリズムはトレーニングプロセス中にlr学習率を最適化します)

  • 利点:SGDよりも優れて高速で、他の最適化アルゴリズムよりも安定しています(どちらを選択するかわからない場合は、Adamを使用してください)
import torch
from torch import nn, optim
optimizer = optim.Adam(model.parameters(), lr, weight_decay=0.1)

Adam最適化アルゴリズムを使用すると、lrを適切に調整できます。

方法はより安定しています(どちらを選択するかわからない場合は、Adamを使用してください)

import torch
from torch import nn, optim
optimizer = optim.Adam(model.parameters(), lr, weight_decay=0.1)

Adam最適化アルゴリズムを使用すると、lrを適切に調整できます。

モデルを保存してモデルをロードする

モデルを保存します

torch.save()保存に使用

モデルを保存するには、モデルをディスクにシリアル化します。Pytorchは、シリアル化にPythonのpickleプログラムを使用します。

pytorchでは、モデル、テンソル、辞書をすべてディスクにシリアル化できます。

関数プロトタイプ:torch.save(obj, f, pickle_model=<module '...'>, pickle_protocol=2)

パラメータ 説明
obj オブジェクトを保持します
f 保存されたファイル名の文字列(またはファイルのようなオブジェクト)
pickle_module メタデータとオブジェクトを選択するためのモジュール
pickle_protocol デフォルトのパラメータを上書きするには、pickleprotocalを指定します

フォーマット.pt\.pth\.pklモデルの3つすべてが問題なく、形式に違いはなく、接尾辞だけが異なります

モデル全体を保存する

モデル全体の结构ANDを参数保存します。

モデル全体をロードする場合、モデルをリファクタリングする必要はなく、変数をモデルとして直接ロードします。

# 用 pt pth pkl ckpt都可以
torch.save(model, "model.pt")

モデルのパラメータのみを保存します

モデルのパラメーターのみを保存します。ロードするときは、モデルをインスタンス化して(構造を取得)、パラメーターをロードする必要があります。

これにはモデルクラスが必要です(モデルフォーム全体を保存する場合、モデルクラスは必要ありません)

# 用 pt pth pkl ckpt都可以
torch.save(model.state_dict(), "model_params.pt")

保存されたモデルファイルのハイパーパラメータ

torch.save({
    
    
    'epoch': epoch,
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'loss': loss
}, "model.pt")

# 加载
model = MyModel()
optimizer = optim.SGD(*args, **kwargs)

checkpoint = torch.load("model.pt")

model.load_state_dict(checkpoint["model_state_dict"])
optimizer.load_state_dict(checkpoint["optimizer_state_dict"])
epoch = checkpoint["epoch"]
loss = checkpoint["loss"]

# 或model.train()
model.eval()

複数のモデルをファイルに保存

torch.save({
    
    
    "modelA_state_dict": modelA.state_dict(),
    "modelB_state_dict": modelB.state_dict()
}, "models_params.pt")

# 加载
checkpoint = torch.load("models_params.pt")
modelA = MyModelA()
modelB = MyModelB()
modelA.load_state_dict(checkpoint["modelA_state_dict"])
modelB.load_state_dict(checkpoint["modelB_state_dict"])

modelA.train()
modelB.train()

微調整を使用してモデルを事前トレーニングします

# 保存预训练模型A
torch.save(model.state_dict(), "model_param.pt")

# 加载预训练模型A到模型B中
model.load_state_dict("model_param.pt", strict=False)

この部分は、転移学習で非常に一般的に使用されます

事前トレーニングのためにいくつかのモデルパラメータをロードすると、キーの不一致が発生する可能性があります(モデルの重みは保存され、キーと値のペアの形式でロードされます)。したがって、キーの不足や過剰なキーに関係なく、load_state_dict()関数でstrictパラメーターをFalseに設定することにより、一致しないキーを無視できます。

特定のレイヤーのパラメーターを他のレイヤーにロードしたいが、一部のキーが一致しない場合は、state_dictのパラメーターのキーを変更して、この問題を解決します。

モデルをロードします

モデルをpytorchにロードするには、Pythonの選択解除ツールを使用して、ディスク上のモデルをメモリに逆シリアル化します。

モデル全体をロードする

関数プロトタイプ:torch.load(f, map_location=None, puckle_model=<module 'pickle' from '...'>)

パラメータ 説明
f ファイル名(またはファイルのようなオブジェクト)を保存するための文字列
map_location 関数または辞書は、ストレージデバイスをマップする方法を指定します
puckle_module メタデータとオブジェクトのピクル解除用モジュール(ファイルをシリアル化する必要がある場合はpickle_module)
# 用 pt pth pkl 都可以
# 加载模型到cpu上
model = torch.load("model.pt")

# 加载模型到cpu上
model = torch.load("model.pt", map_location=torch.device('cpu'))

# 使用方法的形式,加载模型到cpu上
model = torch.load("model.pt", map_location=lambda storage, loc: storage)

# 加载模型到gpu1上
model = torch.load("model.pt", map_location=lambda storage, loc: storage.cuda(1))

# 将模型从gpu1映射到gpu0上
model = torch.load("model.pt", map_location={
    
    'cuda:1': 'cuda:0'})


# 注意一定要使用model.eval()来固定dropout和归一化层,否则每次推理会生成不同的结果
# 或model.train()
model.eval()

モデルパラメータをロードします

関数プロトタイプ:torch.nn.Module.load_state_dict(state_dict, strict=True)

パラメータ 説明
state_dict モデルを保存するための辞書
厳格 state_dictのキーは、model.state_dict()によって返されるキーと一致していますか?
model = MyModel()
# 模型将加载的权重复制到模型的权重中去
model.load_state_dict(torch.load("model_params.pt"))


# 注意一定要使用model.eval()来固定dropout和归一化层,否则每次推理会生成不同的结果
# 或model.train()
model.eval()

ドロップアウトと正規化レイヤーを修正するには、model.eval()を使用する必要があることに注意してください。そうしないと、推論ごとに異なる結果が生成されます。(または使用model.train()

おすすめ

転載: blog.csdn.net/qq_43477218/article/details/114179502