pytorch學習筆記(一)之線性模型
2020.1.27筆記
- Grad在反向傳播過程中是累加的,意味着每一次運行反向傳播,梯度都會累加之前的梯度,一般在方向傳播之前把梯度清零。
- 不允許張量對張量求導,只允許標量對張量求導,求導結果是和自變量同行的張量。
- 可以用with torch.no_grad()將不想被追蹤的操作代碼塊包裹起來。
- Torch變量帶requires_grad的不能進行+=操作。x+=2。
- 批量大小和學習率的值是人爲設定的,不是通過模型訓練學出的,稱之爲超參數。
- Python super()函數用於調用父類(超類)的一個方法。
- a.numpy()將a轉換成numpy數據類型,torch.from_numpy()將numpy轉換爲tensor。
- torch.cuda.is_available()判斷是否支持gpu,a.cuda()就能夠將tensor a放到gpu上面。
- torch.autograd.Variable會被放入計算圖中,然後進行前向傳播和反向傳播,自動求導
包含三個部分data,grad,grad_fn。from torch.autograd import Variable
通過data可以去除variable裏面的tensor數值
Grad_fn表示的是得到這個variable的操作
Grad是這個variable反向傳播梯度
求導y.backward(),對於標量求導裏面的參數可以不寫
對於向量求導不能直接寫成y.backward()。需要傳入參數聲明。比如y.backward(torch.FloatTensor([1,1,1])),得到的就是每個分量的梯度。
2020.1.28筆記
- 優化算法:是一種調整模型參數更新的策略
一階優化算法,使用各個參數的梯度值來更新參數,梯度下降。
二階優化算法,使用了二階導數,hessian方法,來最小化或者最大化損失函數。
torch.optim是一個實現各種優化算法的包。在調用時將需要優化的參數傳入,這些參數都必須是Variable,然後傳入一些基本的設定,比如學習率和動量等。
優化之前,需要先將梯度歸0,optimizer.zeros(),然後通過loss.backward()自動求導得到每個參數的梯度,最後只需要optimizer.step()就可以通過梯度做一步參數更新。 - torch.save用於保存模型的結構和參數。保存方式兩種:
保存整個模型的結構信息和參數信息,保存的對象是model
保存模型的參數,保存的對象是模型的狀態。model.state_dict()。
torch.save(model, ‘./model.pth’)
torch.save(model.state_dict(), ‘./model_state.pth’)
3.加載模型
加載完整的模型結構和參數信息
Load_model = torch.load('model.pth’),網絡較大的時候加載時間較長,同時存儲空間也比較大。
加載模型參數信息,需要先導入模型的結構,然後
model.load_state_dic(torch.load(‘model_state.pth’))導入。
4.線性迴歸案例。
給出一系列點,找到擬合的直線。model.eval()將模型變成測試模式,一些層如dropout和batchNormalization在訓練和測試的時候是不一樣的,因而需要通過這樣一個操作來轉換這些不一樣的層操作。
import torch
from torch import nn,optim
import numpy as np
import matplotlib.pyplot as plt
from torch.autograd import Variable
#線性迴歸,輸入數據(x1,y1),(x2,y2),...,(xn,yn)
x_train = np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],
[9.779],[6.182],[7.59],[2.167],[7.042],
[10.791],[5.313],[7.997],[3.1]],dtype=np.float32)
y_train = np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],
[3.366],[2.596],[2.53],[1.221],[2.827],
[3.465],[1.65],[2.904],[1.3]],dtype=np.float32)
#轉爲tensor
x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train)
#定義線性迴歸網絡結構
class LinearRegression(nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(1,1)
def forward(self, x):
out = self.linear(x)
return out
#定義在gpu上的LinearRegression成員
if torch.cuda.is_available():
model = LinearRegression().cuda()
else:
model = LinearRegression()
#定義損失函數
criterion = nn.MSELoss()
#定義優化函數
optimizer = optim.SGD(model.parameters(), lr=1e-3)
num_epochs = 1000
for epoch in range(num_epochs):
if torch.cuda.is_available():
inputs = Variable(x_train).cuda()
target = Variable(y_train).cuda()
else:
inputs = Variable(x_train)
target = Variable(y_train)
#forward
out = model.forward(inputs)
loss = criterion(out, target)
#backward
#梯度清0
optimizer.zero_grad()
#反向傳播
loss.backward()
#參數更新
optimizer.step()
if (epoch+1)%40 == 0:
print('loss:', loss.data)
#將模型轉爲測試模式
model.eval()
#預測結果
predict = model.forward(Variable(x_train).cuda())
#轉成cpu,轉爲numpy
predict = predict.data.cpu().numpy()
plt.plot(x_train.numpy(), y_train.numpy(), 'ro', label='Original data')
plt.plot(x_train.numpy(), predict, label='Fitting Line')
plt.show()
2020.1.29筆記
多項式迴歸
- Torch.unsqueeze()對數據維度進行擴充
a.unsqueeze(1)在第二維增加一個維度
torch.squeeze()對數據進行降維,只有維度值爲1時纔會去掉改維度。 - tensor.size()
import torch
import numpy as np
test = torch.tensor([0,1,2])
print(test.size())
print(test[0], test[1], test[2])
test = torch.tensor([[0,1,2]])
print(test.size())
print(test[0])
print(test[0][0], test[0][1], test[0][2])
運行結果爲:
torch.Size([3])
tensor(0) tensor(1) tensor(2)
torch.Size([1, 3])
tensor([0, 1, 2])
tensor(0) tensor(1) tensor(2)
3.torch.mm()爲矩陣乘法
x.mm(w_target)
4.
import torch
import numpy as np
from torch import nn, optim
from torch.autograd import Variable
import matplotlib.pyplot as plt
#生成特徵點
def make_features(x):
#在第二個維度添加一個維度
#print("before x.size:", x.size())
x = x.unsqueeze(1)
#print("x:", x)
#print("after x.size:", x.size())
return torch.cat([x**i for i in range(1,4)], 1)
w_target = torch.FloatTensor([0.5, 3, 2.4]).unsqueeze(1)
#print('w_target: ', w_target)
b_target = torch.FloatTensor([0.9])
#將每次輸入一個x得到一個y的真實函數
def f(x):
return x.mm(w_target) + b_target
#得到batch_size個訓練集
def get_batch(batch_size=32):
#生成batch_size個隨機數
random = torch.randn(batch_size)
x = make_features(random)
y = f(x)
if torch.cuda.is_available():
return Variable(x).cuda(), Variable(y).cuda()
else:
return Variable(x), Variable(y)
#定義多項式模型
class poly_model(nn.Module):
def __init__(self):
super(poly_model, self).__init__()
#模型輸入爲3維,輸出是1維
self.poly = nn.Linear(3,1)
def forward(self, x):
out = self.poly(x)
return out
def main():
if torch .cuda.is_available():
model = poly_model().cuda()
else:
model = poly_model()
criterion = nn.MSELoss()
#使用隨機梯度下降來優化模型
optimizer = optim.SGD(model.parameters(), lr=1e-3)
#開始訓練模型
epoch = 0
while True:
# 獲取數據集
batch_x, batch_y = get_batch()
#前向傳播
output = model.forward(batch_x)
#計算損失
loss = criterion(output, batch_y)
#打印損失值
print_loss = loss.data
#梯度清0
optimizer.zero_grad()
#反向傳播
loss.backward()
#更新參數
optimizer.step()
epoch += 1
if print_loss < 1e-3:
break
print('loss: %.3f after batches: %d' %(print_loss, epoch))
w_0, w_1, w_2 = model.poly.weight[0]
w_0 = w_0.data.item()
w_1 = w_1.data.item()
w_2 = w_2.data.item()
b_ = model.poly.bias[0].item()
x = np.arange(-1,1,0.1)
w0_truth = w_target[0].item()
w1_truth = w_target[1].item()
w2_truth = w_target[2].item()
b_truth = b_target.item()
y = w0_truth * x + w1_truth * x * x + w2_truth * x * x * x + b_truth
y_ = w_0 * x + w_1 * x * x + w_2 * x * x * x + b_
print('truth result:')
print('w0:%.3f,w1:%.3f,w2:%.3f,b:%.3f' % (w0_truth, w1_truth, w2_truth, b_truth))
print('train result:')
print('w0:%.3f,w1:%.3f,w2:%.3f,b:%.3f' % (w_0, w_1, w_2, b_))
plt.figure()
plt.plot(x, y, 'ro')
plt.plot(x, y_, 'b-')
plt.legend(['actual curve', 'predict curve'])
plt.show()
if __name__ == '__main__':
main()