-
聲明
以下均基於置入以下包
import torch
import numpy as np
from torch.autograd import Variable
import torchvision
import torch.nn as nn
from torchvision import transforms
-
變量Variable
x=torch.FloatTensor([1.,2.,3.])
# x=torch.randn(3)
print(x)
x_var = Variable(x,requires_grad =True)
y=x_var*2
print(y)
y.backward(torch.FloatTensor([1,0.1,0.01]))#原本三個維度的梯度都是2,使用參數聲明後梯度乘上了[1,0.1,0.01]
print(x_var.grad,x_var.data,y.grad_fn)#變量的三個屬性:梯度、值、得到變量的操作
#result:
# tensor([1., 2., 3.])
# tensor([2., 4., 6.], grad_fn=<MulBackward>)
# tensor([2.0000, 0.2000, 0.0200]) tensor([1., 2., 3.]) <MulBackward object at 0x7f7441fcb940>
-
數據集載入
test_set = torchvision.datasets.ImageFolder('dataset/test', transform=test_input_transform)
data_loader = torch.utils.data.DataLoader(test_set, batch_size=8, num_workers=2, shuffle=True)
-
自定義一個網絡
class mynet(nn.Module):
def __init__(self, dim_in, dim_out):
super(mynet, self).__init__()
self.main = nn.Sequential(
nn.Conv2d(dim_in, dim_out, kernel_size=3, stride=1, padding=1, bias=False),
nn.InstanceNorm2d(dim_out, affine=True, track_running_stats=True),
nn.ReLU(inplace=True),
nn.Conv2d(dim_out, dim_out, kernel_size=3, stride=1, padding=1, bias=False),
nn.InstanceNorm2d(dim_out, affine=True, track_running_stats=True))
def forward(self, x):
return x + self.main(x)
sequential實現網絡層的組合,還有一種增加塊的方式定義網絡,這個方法可以對每一層加名字。
layer1=nn.Sequential()
layer1.add_module('conv1',nn.Conv2d(3,32,3,1,1))
layer1.add_module('relu1',nn.ReLu(True))
layer1.add_module('pool1',nn.Maxpool2d(2,2))
self.layer1=layer1
-
遍歷網絡/提取網絡層結構
在檢查文件夾的文件時,有os.listdir這種一層一層的,也有os.walk這種到底的,網絡的遍歷也同樣。
class mynet(nn.Module):
def __init__(self):
super(mynet, self).__init__()
layer1 = nn.Sequential()
layer1.add_module('conv1', nn.Conv2d(3, 32, 3, 1, 1))
layer1.add_module('relu1', nn.ReLU(True))
layer1.add_module('pool1', nn.MaxPool2d(2, 2))
self.layer1 = layer1
layer2 = nn.Sequential()
layer2.add_module('conv2', nn.Conv2d(32, 64, 3, 1, 1))
layer2.add_module('relu2', nn.ReLU(True))
layer2.add_module('pool2', nn.MaxPool2d(2, 2))
self.layer2 = layer2
layer3 = nn.Sequential()
layer3.add_module('fc', nn.Linear(64,10))
self.layer3 = layer3
def forward(self, x):
x=self.layer1(x)
x=self.layer2(x)
x=self.layer3(x)
return x
model=mynet()
#.children() 下一級模塊迭代器,這裏下一級就是三層網絡
a=list(model.children())
#.modules()返回所有模塊迭代器,有點os.walk的意思,整個網絡-第一層-第一層下面各個層=第二層-。。。
b=list(model.modules())
#.named_children() 返回網絡層名字及迭代器
c=list(model.named_children())
#.named_modules() 返回網絡層名字及所有模塊迭代器
d=list(model.named_modules())
for layer in model.modules():
# print(layer)
print(isinstance(layer,nn.Conv2d))
-
常用的層
nn.Conv2d
nn.ReLu
nn.MaxPool2d
nn.Linear
nn.Dropout()#一般放在Relu後,Linear前
全連接層前的展平操作:
x = x.view(x.size(0), -1)#from ([[batch_size, 512, 1, 1]]) to ([batch_size, 512])
-
損失
criterion = nn.CrossEntropyLoss()#交叉熵損失
criterion = nn.MSELoss()#均方誤差
criterion = BCELoss()#二分類損失,如sigmoid輸出
loss=criterion(out,target)
-
優化
optimizer = torch.optim.SGD(model.parameters(),lr=0.01,momentum = 0.9)
optimizer.zero_grad()#optimizer.zeros()優化之前梯度清零
loss.backward()#反向傳播
optimizer.step()#參數更新
-
模型加載與保存
#保存模型結構及參數
torch.save(model,model_path)
load_model = torch.load(model_path)
#保存模型參數
torch.save(model.state_dict(),model_path)
model.load_state_dict(torch.load(model_path))
#遷移一部分參數
pretrained_dict = torch.load(model_path)
model_dict = model.state_dict()
pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
model_dict.update(pretrained_dict)
model.load_state_dict(model_dict)
-
網絡測試
model.eval()
例如Dropout、BN在訓練階段和測試階段不一樣,需要eval的操作來轉換這種層的操作。
BN:
訓練:
由於在訓練階段低層更新了參數,導致高層輸入數據變化,因此在高層輸入時,加入歸一化操作(比如把第三層歸一化到均值0,方差1)
使用到的兩個參數分別爲每一批數據的均值,每一批數據的標準差。
測試:
BN一般放在全連接層後面,非線性層前面
-
數據擴充transforms
transforms.Compose(#Compose組合預處理操作,各個操作是以list的形式存放的
[transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))]
)
更多transforms方式:https://blog.csdn.net/u011995719/article/details/85107009