Pytorch知识点学习
- 1 Numpy
- 1.1 生成Numpy数组
- 1.2 获取元素
- 1.3 Numpy的算术运算
- 1.4 数组变形
- 1.5 批量处理
- 1.6 通用函数
- 1.7 广播机制
- 2 PyTorch
- 2.1 Numpy与Tensor
- 2.2 Tensor与Autograd
- 2.3使用Numpy实现参数更新
- 2.4使用Tensor及Antograd实现参数更新
- 3 PyTorch神经网络工具箱
- 3.1 实现神经网络实例
- 3.3 如何构建神经网络?
- 4 PyTorch数据处理工具箱
- 4.1 数据处理工具箱概述
- 4.2 utils.data简介
- 4.3 torchvision简介
- 4.4 可视化工具
- 5 机器学习
- 6 视觉处理基础
- 6 相关的数学知识
1 Numpy
本节要点:
- ·如何生成Numpy数组。
- 如何存取元素。
- Numpy的算术运算。
- 数组变形。
- 批量处理。
- Numpy的通用函数。
- Numpy的广播机制。
1.1 生成Numpy数组
- 从已有数据中创建数组
import numpy as np
# np.+Tab键,查看可使用的函数
# np.abs? 可查看函数abs的详细帮助信息
# random创建,创建特定形状的多维数组
list1 = [1,2,3]
ls1 = np.array(list1)
ls1.dtype
ls1.ndim
type(ls1)
list2 = [[1,2,3],[4,5,6]]
ls2 = np.array(list2)
len(list2)
ls2.ndim
- 利用random模块生成数组
np.random.random(100).reshape(10,10).shape
np.random.uniform()
np.random.uniform(0,1,[2,3])
np.random.randn(10)
np.random.randint(0,255,dtype=np.uint8)
np.random.randint(0,255,[2,3],dtype=np.uint8)
np.random.normal(10,100,[2,3])
arr = np.arange(10).reshape(2,5)
np.random.shuffle(arr)
arr
np.random.sample(20)
- 创建特定形状的多维数组
a = np.zeros([3,3])
b = np.ones([3,3])
c = np.empty([2,3])
a0 = np.zeros_like(a)
b0 = np.ones_like(b)
c0 = np.empty_like(c)
np.eye(5)
np.full([2,3],10)
# 应用
img = np.random.randint(0,255,[5,5],dtype=np.uint8)
mask = np.zeros_like(img,dtype=np.bool)
mask[1:4,1:4] = 1
img0 = img[mask]
img = np.random.randint(0,255,[5,5],dtype=np.uint8)
mask = np.zeros_like(img)
mask[1:4,1:4] = 1
img1 = img*mask
np.savetxt(X=img0,fname = '/Users/ls/PycharmProjects/LS_Test/img0.txt')
t = np.loadtxt('/Users/ls/PycharmProjects/LS_Test/img0.txt')
- 利用arange、linspace函数生成数组
np.arange(1,10,2)
np.arange(2,10,2)
x = np.linspace(0, 1, 10)
y = np.sin(x)
1.2 获取元素
1.获取元素
n11 = np.random.randint(0,10,10)
n11[5]
n11[:3]
n11[4:8]
n11[2:9:2]
n11[::-1]
n11[::-3]
n11[::3]
n45 = np.random.randint(0,10,[4,5])
n45[1,3]
n45[[1,3],:]
n45[[1,3],2:4]
n45[[1,3],[1,3,5]]
n45[[1,3],:][:,[0,4]]
n45[(n45>3)&(n45<9)]
- random.choice函数从指定的样本中随机抽取数据。
a=np.arange(1,25,0.5,dtype=float)
s1 = np.random.choice(a,10)
s2 = np.random.choice(a,[3,4],replace=True)
s3 = np.random.choice(a,[3,4],p=a/sum(a))
1.3 Numpy的算术运算
Numpy的算术运算,一种是对应元素相乘,又称为逐元乘法(Element-Wise Product),运算符为 np.multiply(),或*。另一种是点积或内积元素,运算符为np.dot()。
- 对应元素相乘
np.random.randint(0,10,[2,3])
B = np.random.randint(3,12,[2,3])
A,B
A*B
np.multiply(A,B)
A*2 # 广播机制
A/2
A*np.full([2,3],2)
# [2,3]
# [1,1]
# [2,3]
#
# [2,4]--> [2,1,4]-->[2,3,4]
# [3,4]--> [1,3,4]-->[2,3,4]
A = np.random.randint(0,10,[2,4])
B = np.random.randint(0,10,[3,4])
np.expand_dims(A,1)+np.expand_dims(B,0)
- 点积运算
A = np.random.randn(3,5)
B = np.random.randn(5,3)
np.dot(A,B)
a.dot(B)
B.dot(A)
1.4 数组变形
- 更改数组的形状
np.reshape() # 不修改arr本身
np.resize() # 修改arr本身
arr.T # 转置
arr.ravel() # 不产生原数组的副本
arr.faltten() # 返回原数组的副本
arr.squeeze() # 降维
arr.transpose() # 调整坐标轴位置
a = np.random.randint(0,10,[2,3])
a.reshape(3,2) # 不改变变量本身
a
a.resize([3,2]) # 改变变量本身
a
a.T
a.ravel() # 不改变变量本身
a.ravel('F')
a
a.flatten() # 不改变变量本身
a
a.squeeze()
a = np.random.randint(0,10,[1,2,3,4,1])
a.squeeze().shape
a.transpose()
- 合并数组
np.append() # 占内存
np.concatenate() # 没有内存问题
np.stack() # 增加新的轴
np.hstack() # 按照行堆砌
np.vstack() # 按照列堆砌
np.dstack() # 按照第d维堆砌
np.vsplit() # 按照列分割
# append和concatenate,按照行(列)合并时,必须要求数组有相同的列(行),即其他坐标轴的数值相等。
# stack、hstack、dstack,要求待合并的数组必须具有相同的形状(shape)。
a0 = np.random.randint(0,10,[4,2,3,4])
a1 = np.random.randint(0,10,[3,2,3,4])
a01 = np.append((a0,a1),0)
a01 = np.append(a0,a1,0)
a01.shape
a01 = np.concatenate((a0,a1),0)
a01.shape
a0 = np.random.randint(0,10,[4,2,3,4])
a1 = np.random.randint(0,10,[4,2,3,4])
a = np.stack(a0,a1)
a = np.stack((a0,a1))
a.shape
np.hstack((a0,a1)).shape
np.vstack((a0,a1)).shape
np.dstack((a0,a1)).shape
np.stack((a0,a1),-1).shape
np.vsplit(a,0)
np.vsplit(a,2)[0].shape
1.5 批量处理
samples = np.random.randn(1000,3,2)
np.random.shuffle(samples)
bs = 100
for i in range(0,1000,bs):
s_sum = np.sum(samples[i:i+bs])
print(f'epoch:{i},sum of data:{s_sum}')
1.6 通用函数
s= np.random.randint(0,10,[3,4,5])
np.sqrt(s)
np.sin(s)
np.log10(s)
np.exp(s)
np.sum(s,0).shape
np.mean(s,2).shape
np.median(s)
np.median(s,0)
np.median(s,1)
np.median(s,2)
np.std(s)
np.std(s,0)
np.std(s,1)
np.std(s,2)
np.var(s)
np.var(s,0)
np.var(s,1)
np.var(s,2)
np.corrcoef(s[0])
1.7 广播机制
两个数组能否做数学运算,把数组的shape右对齐排列,如果对应位置上的数值为1、相同、不存在就可以运算,反之需要增加维度才可以运算。
[2,3]
[ 3]
[2,3]
[3,1,5]
[1,4,5]
[3,4,5]
[2,3]
[2,3]
[2,3]
[2,3]-->[1,2,1,3]
[3,2]-->[3,1,2,1]
[3,2,2,3]
(np.random.randn(2,3)+np.random.randn(3)).shape
(np.random.randn(3,1,5)+np.random.randn(1,4,5)).shape
(np.random.randn(2,3)+np.random.randn(2,3)).shape
(np.expand_dims(np.random.randn(2,3),[0,2])+np.expand_dims(np.random.randn(3,2),[1,3])).shape
2 PyTorch
本章要点:
- Numpy与Tensor。
- Tensor与Autograd。
- 使用Numpy实现机器学习。
- 使用Tensor及Antograd实现机器学习。
- 使用TensorFlow架构。
2.1 Numpy与Tensor
1 Tensor
import torch
import numpy as np
a = torch.tensor([1,2])
b = torch.tensor([1,2])*2
torch.add(a,b)
a.add_(b) # 改变a的值,修改自身数据
a.add(b) # 不改变a的值
2 创建Tensor
a = torch.tensor([[1,2]])
torch.eye(3)
torch.eye(3,4)
torch.linspace(0,100,10)
torch.logspace(1,3,10)
torch.rand(3,3)
torch.ones(3,4)
torch.zeros(5,6)
torch.ones_like(a)
torch.zeros_like(a)
torch.arange(0,10,0.9)
b=np.array([1,2,3])
torch.from_numpy(b)
t=torch.Tensor([[1,2,3],[4,5,6]])
t.size()
t.shape
torch.Tensor(t.size())
1)torch.Tensor是torch.empty和torch.tensor之间的一种混合,但是,当传入数据时,
torch.Tensor使用全局默认dtype(FloatTensor),而torch.tensor是从数据中推断数据类型。
2)torch.tensor(1)返回一个固定值1,而torch.Tensor(1)返回一个大小为1的张量,它是
随机初始化的值。
torch.tensor(1)
torch.Tensor(1)
torch.tensor(1).type()
torch.Tensor(1).type()
3 修改Tensor形状
a = torch.randn(3,4)
a.size()
a.numel()
a.view(2,6)
a.reshape(2,6)
a.resize(2,6)
a.view(-1)
[i.item() for i in a.flatten()]
[i.item() for i in a.view(-1)]
a.unsqueeze([0,-1]).shape
a.squeeze().shape
4 索引操作
a = torch.randn(10,5,4)
torch.index_select(a,0,torch.tensor([0,2]))
b = torch.zeros(10)
b[5:]+=torch.rand(5)
b.nonzero()
mask = b>0.5
torch.masked_select(b,mask)
torch.gather(b,0,torch.tensor([2,3]))
torch.gather(b,0,torch.tensor([2,3,7,9]))
torch.scatter(b,0,torch.tensor([2,3,7,9]),100)
5 广播机制
a = torch.tensor([1,2,3])
a.expand(4,3)
6 逐元素操作
x1 = -torch.randint(0,10,[2,3])
x2 = torch.randint(0,10,[2,3])
torch.abs(x1)
torch.add(x1,x2)
x1.add_(x2)
t = torch.randn(1, 3)
t1 = torch.randn(3, 1)
t2 = torch.randn(1, 3)
torch.addcdiv(t, t1, t2, value=0.1)
torch.addcmul(t, t1, t2, value=0.1)
t.ceil()
t.floor()
t.clamp(-0.03,0.02)
t.exp()
t.log()
t.pow(2)
t.mul(3)
t.neg()
t.sigmoid()
t.tanh()
t.softmax(dim=0)
7 归并操作
a = torch.randint(0,10,[2,3])
b = torch.randint(0,10,[2,3])
a.cumprod(1)
a.cumsum(1)
torch.dist(a*1.,b*1.,p=2)
(a*1.).mean(0)
torch.norm(a*1.,p=2)
a.prod(1)
8 比较操作
a = torch.randn(4,5)
b = a*1.0
a.eq(b)
a.equal(b*2)
a.max(1)
a.min(0)
a.ge(b)
a.le(b*0.2)
a.gt(b*2)
a.lt(b*0.2)
torch.topk(a,1)
9 矩阵操作
1)Torch的dot与Numpy的dot有点不同,Torch中的dot是对两个为1D张量进行点积运 算,Numpy中的dot无此限制。
2)mm是对2D的矩阵进行点积,bmm对含batch的3D进行点积运算。
3)转置运算会导致存储空间不连续,需要调用contiguous方法转为连续。
a = torch.rand(3)
b = torch.rand(3)
torch.dot(a,b)
a = torch.rand(2,3)
b = torch.rand(2,3)
torch.mm(a,b.T)
b.t()
b.svd()
a = torch.rand(3)
b = torch.rand(2,3)
torch.mv(b,a)
a = torch.rand(2,3,4)
b = torch.rand(2,4,3)
torch.bmm(b,a)
2.2 Tensor与Autograd
1 自动求导要点
为实现对Tensor自动求导,需考虑如下事项:
1)创建叶子节点(Leaf Node)的Tensor,使用requires_grad参数指定是否记录对其 的操作,以便之后利用backward()方法进行梯度求解。requires_grad参数的缺省值为 False,如果要对其求导需设置为True,然后与之有依赖关系的节点会自动变为True。
2)可利用requires_grad_()方法修改Tensor的requires_grad属性。可以调用.detach()或 with torch.no_grad():,将不再计算张量的梯度,跟踪张量的历史记录。这点在评估模 型、测试模型阶段中常常用到。
3)通过运算创建的Tensor(即非叶子节点),会自动被赋予grad_fn属性。该属性表 示梯度函数。叶子节点的grad_fn为None。
4)最后得到的Tensor执行backward()函数,此时自动计算各变量的梯度,并将累加结 果保存到grad属性中。计算完成后,非叶子节点的梯度自动释放。
5)backward()函数接收参数,该参数应和调用backward()函数的Tensor的维度相同, 或者是可broadcast的维度。如果求导的Tensor为标量(即一个数字),则backward中的参 数可省略。
6)反向传播的中间缓存会被清空,如果需要进行多次反向传播,需要指定backward 中的参数retain_graph=True。多次反向传播时,梯度是累加的。
7)非叶子节点的梯度backward调用后即被清空。
8)可以通过用torch.no_grad()包裹代码块的形式来阻止autograd去跟踪那些标记
为.requesgrad=True的张量的历史记录。这步在测试阶段经常使用。
2.3使用Numpy实现参数更新
用Numpy求解梯度
y = w*x^2+b
1. 生成样本x,y.
2. 计算预测值、损失,参数梯度。
3. 初始化参数,迭代循环更新参数,直到循环结束或者参数收敛。
import torch
import numpy as np
# 1 数据集
N = 1000
w = 1.3
b = 1
lr = 1e-3
x = torch.linspace(-1,1,N) # [1000]
y = w*torch.pow(x,2)+b # [1000]
epoch = 60
w = torch.rand(1)
b = torch.rand(1)
for i in range(epoch):
y_ = w*torch.pow(x,2)+b
loss = 1/2*torch.sum((y_-y)**2)
w -= lr*torch.sum((y_-y)*torch.pow(x,2))
b -= lr*torch.sum(y_-y)
if i%10 == 0:
print(f'i:{i},w:{w},b:{b}')
2.4使用Tensor及Antograd实现参数更新
N = 1000
w =1.3 #torch.tensor([[1.3]])
b = 1
lr = 1e-3
x = torch.linspace(-1,1,N) # [1000]
y = w*torch.pow(x,2)+b+torch.rand(1000)*0.01 # [1000]
epoch = 120
w = torch.randn(1,dtype=torch.float32,requires_grad=True)
b = torch.randn(1,dtype=torch.float32,requires_grad=True)
for i in range(epoch):
y_ = w*torch.pow(x,2)+b
loss = 1/2*torch.sum((y_-y)**2)
loss.backward()
with torch.no_grad():
w -= lr*w.grad
b -= lr*b.grad
w.grad.zero_()
b.grad.zero_()
if i%10 == 0:
print(f'i:{i},w:{w},b:{b}')
3 PyTorch神经网络工具箱
- 介绍神经网络核心组件。
- 如何构建一个神经网络。
- 详细介绍如何构建一个神经网络。
- 如何使用nn模块中Module及functional。
- 如何选择优化器。
- 动态修改学习率参数。
3.1 实现神经网络实例
- 主要步骤
1)数据集。
2)利用torchvision对数据进行预处理,调用torch.utils建立一个数据迭代器。
3)可视化源数据。
4)利用nn工具箱构建神经网络模型。 5)实例化模型,并定义损失函数及优化器。
6)训练模型。
7)可视化结果。
# 1.导人必要的模块
import torch
import numpy as np
from torchvision.datasets import mnist
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import torch.nn.functional as F
import torch.optim as optim
from torch import nn
# 2.定义一些超参数
train_batch_size = 8
test_batch_size = 8
learning_rate = 0.01
num_epoches = 20
lr = 0.01
momentum = 0.5
# 下载数据并对数据进行预处理
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5],[0.5])])
train_dataset = mnist.MNIST('./data',train=True,transform=transform,download=True)
test_dataset = mnist.MNIST('./data',train=True,transform=transform)
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)
# 3可视化源数据
examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)
fig = plt.figure()
for i in range(6):
plt.subplot(2,3,i+1)
plt.tight_layout()
plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
plt.title("Ground Truth: {}".format(example_targets[i]))
plt.xticks([])
plt.yticks([])
# 4 构建模型
class Net(nn.Module):
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super(Net, self).__init__()
self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1))
self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d (n_hidden_2))
self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim))
def forward(self, x):
x = F.relu(self.layer1(x))
x = F.relu(self.layer2(x))
x = self.layer3(x)
return x
# 4.2 实例化网络。
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") #实例化网络
model = Net(28 * 28, 300, 100, 10)
model.to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)
# 5 训练模型
# 5.1 开始训练
losses = []
acces = []
eval_losses = []
eval_acces = []
for epoch in range(num_epoches):
train_loss = 0
train_acc = 0
model.train() #动态修改参数学习率
if epoch%5==0:
optimizer.param_groups[0]['lr'] *= 0.1
for img, label in train_loader:
img = img.to(device)
label = label.to(device)
img = img.view(img.size(0), -1)
# 前向传播
out = model(img)
loss = criterion(out, label)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 记录误差
train_loss += loss.item()
# 计算分类的准确率
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
train_acc += acc
losses.append(train_loss / len(train_loader))
acces.append(train_acc / len(train_loader))
# 在测试集上检验效果
eval_loss = 0
eval_acc = 0 # 将模型改为预测模式
model.eval()
for img, label in test_loader:
img = img.to(device)
label = label.to(device)
img = img.view(img.size(0), -1)
out = model(img)
loss = criterion(out, label)
# 记录误差
eval_loss += loss.item()
# 记录准确率
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
eval_acc += acc
eval_losses.append(eval_loss / len(test_loader))
eval_acces.append(eval_acc / len(test_loader))
print('epoch: {}, Train Loss: {:.4f}, Train Acc: {:.4f},\
Test Loss: {:.4f}, Test Acc: {:.4f}'
.format(epoch, train_loss / len(train_loader), \
train_acc / len(train_loader), eval_loss / len(test_loader),\
eval_acc / len(test_loader)))
# 5.2 可视化训练及测试损失值
plt.title('trainloss')
plt.plot(np.arange(len(losses)), losses)
plt.legend(['Train Loss'], loc='upper right')
调用model.train()会把所有的module 设置为训练模式。如果是测试或验证阶段,需要使模型处于验证阶段,即调用 model.eval(),调用model.eval()会把所有的training属性设置为False。
1)nn.Xxx继承于nn.Module,nn.Xxx需要先实例化并传入参数,然后以函数调用的方 式调用实例化的对象并传入输入数据。它能够很好地与nn.Sequential结合使用,而 nn.functional.xxx无法与nn.Sequential结合使用。
2)nn.Xxx不需要自己定义和管理weight、bias参数;而nn.functional.xxx需要自己定义 weight、bias参数,每次调用的时候都需要手动传入weight、bias等参数,不利于代码复 用。
3)Dropout操作在训练和测试阶段是有区别的,使用nn.Xxx方式定义Dropout,在调 用model.eval()之后,自动实现状态的转换,而使用nn.functional.xxx却无此功能。
总的来说,两种功能都是相同的,但PyTorch官方推荐:具有学习参数的(例如, conv2d,linear,batch_norm)采用nn.Xxx方式。没有学习参数的(例如,maxpool、loss func、 activation func)等根据个人选择使用nn.functional.xxx或者nn.Xxx方式。3.2小节中使用激 活层,我们采用F.relu来实现,即nn.functional.xxx方式。
3.3 如何构建神经网络?
3.3.1 构建网络层
# 1)导入需要的模块
import torch
import torch.utils.data as Data
import torch.nn.functional as F
import matplotlib.pyplot as plt
# 超参数
LR = 0.01
BATCH_SIZE = 32
EPOCH = 12
# 2)生成数据。
# 生成训练数据
# torch.unsqueeze() 的作用是将一维变二维,torch只能处理二维的数据
x = torch.unsqueeze(torch.linspace(-1, 1, 1000), dim=1)
# 0.1 * torch.normal(x.size())增加噪点
y = x.pow(2) + 0.1 * torch.normal(torch.zeros(*x.size()))
torch_dataset = Data.TensorDataset(x,y)
#得到一个代批量的生成器
loader = Data.DataLoader(dataset=torch_dataset, batch_size=BATCH_SIZE, shuffle=True)
# 3)构建神经网络。
class Net(torch.nn.Module): # 初始化
def __init__(self):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(1, 20)
self.predict = torch.nn.Linear(20, 1)
# 前向传递
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
# 4)使用多种优化器。
net_SGD = Net()
net_Momentum = Net()
net_RMSProp = Net()
net_Adam = Net()
nets = [net_SGD, net_Momentum, net_RMSProp, net_Adam]
opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)
opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.9)
opt_RMSProp = torch.optim.RMSprop(net_RMSProp.parameters(), lr=LR, alpha=0.9)
opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99))
optimizers = [opt_SGD, opt_Momentum, opt_RMSProp, opt_Adam]
# 5)训练模型。
loss_func = torch.nn.MSELoss()
loss_his = [[], [], [], []] # 记录损失
for epoch in range(EPOCH):
for step, (batch_x, batch_y) in enumerate(loader):
for net, opt,l_his in zip(nets, optimizers, loss_his):
output = net(batch_x) # get output for every net
loss = loss_func(output, batch_y) # compute loss for every net
opt.zero_grad() # clear gradients for next train
loss.backward() # backpropagation, compute gradients
opt.step() # apply gradients
l_his.append(loss.data.numpy()) # loss recoder
labels = ['SGD', 'Momentum', 'RMSprop', 'Adam']
# 6)可视化结果。
for i, l_his in enumerate(loss_his):
plt.plot(l_his, label=labels[i])
plt.legend(loc='best')
plt.xlabel('Steps')
plt.ylabel('Loss')
plt.ylim((0, 0.2))
plt.show()
4 PyTorch数据处理工具箱
- 简单介绍PyTorch相关的数据处理工具箱。
- utils.data简介。
- torchvision简介。
- tensorboardX简介及实例。
4.1 数据处理工具箱概述
- torch.utils.data工具包包括以下4个类。
1)Dataset:是一个抽象类,其他数据集需要继承这个类,并且覆写其中的两个方法
(getitem_、len)。
2)DataLoader:定义一个新的迭代器,实现批量(batch)读取,打乱数据
(shuffle)并提供并行加速等功能。
3)random_split:把数据集随机拆分为给定长度的非重叠的新数据集。
4)*sampler:多种采样函数。
- torchvision包括4个类,各类的主要功能如下。
1)datasets:提供常用的数据集加载,设计上都是继承自torch.utils.data.Dataset,主要
包括MMIST、CIFAR10/100、ImageNet和COCO等。
2)models:提供深度学习中各种经典的网络结构以及训练好的模型(如果选择
pretrained=True),包括AlexNet、VGG系列、ResNet系列、Inception系列等。
3)transforms:常用的数据预处理操作,主要包括对Tensor及PIL Image对象的操作。
4)utils:含两个函数,一个是make_grid,它能将多张图片拼接在一个网格中;另一 个是save_img,它能将Tensor保存成图片。
4.2 utils.data简介
utils.data包括Dataset和DataLoader。torch.utils.data.Dataset为抽象类。自定义数据集需 要继承这个类,并实现两个函数,一个是__len__,另一个是__getitem__,前者提供数据 的大小(size),后者通过给定索引获取数据和标签。__getitem__一次只能获取一个数 据,所以需要通过torch.utils.data.DataLoader来定义一个新的迭代器,实现batch读取。首 先我们来定义一个简单的数据集,然后通过具体使用Dataset及DataLoader,给读者一个直 观的认识。
import torch
from torch.utils import data
import numpy as np
# 2)定义获取数据集的类
class TestDataset(data.Dataset):#继承Dataset
def __init__(self):
self.Data=np.asarray([[1,2],[3,4],[2,1],[3,4],[4,5]])#一些由2维向量表示的数据集 self.Label=np.asarray([0,1,0,1,2])#这是数据集对应的标签
def __getitem__(self, index): #把numpy转换为Tensor
txt=torch.from_numpy(self.Data[index])
label=torch.tensor(self.Label[index])
return txt,label
def __len__(self):
return len(self.Data)
# 3)获取数据集中数据
Test=TestDataset()
print(Test[2]) #相当于调用__getitem__(2) print(Test.__len__())
#输出:
#(tensor([2, 1]), tensor(0)) #5
以上数据以tuple返回,每次只返回一个样本。实际上,Dateset只负责数据的抽取,调 用一次__getitem__只返回一个样本。如果希望批量处理(batch),还要同时进行shuffle和 并行加速等操作,可选择DataLoader。DataLoader的格式为:
data.DataLoader( dataset,
batch_size=1,
shuffle=False,
sampler=None,
batch_sampler=None,
num_workers=0,
collate_fn=<function default_collate at 0x7f108ee01620>,
pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None,
)
主要参数说明:
·dataset:加载的数据集。
·batch_size:批大小。
·shuffle:是否将数据打乱。
·sampler:样本抽样。
·num_workers:使用多进程加载的进程数,0代表不使用多进程。
·collate_fn:如何将多个样本数据拼接成一个batch,一般使用默认的拼接方式即可。
·pin_memory:是否将数据保存在pin memory区,pin memory中的数据转到GPU会快 一些。
·drop_last:dataset中的数据个数可能不是batch_size的整数倍,drop_last为True会将多 出来不足一个batch的数据丢弃。
test_loader = data.DataLoader(Test,batch_size=2,shuffle=False,num_workers=2)
for i,traindata in enumerate(test_loader):
print('i:',i)
Data,Label=traindata
print('data:',Data)
print('Label:',Label)
dataiter=iter(test_loader)
imgs,labels=next(dataiter)
一般用data.Dataset处理同一个目录下的数据。如果数据在不同目录下,因为不同的目
录代表不同类别(这种情况比较普遍),使用data.Dataset来处理就很不方便。不过,使用 PyTorch另一种可视化数据处理工具(即torchvision)就非常方便,不但可以自动获取标 签,还提供很多数据预处理、数据增强等转换函数。
4.3 torchvision简介
1 transforms
transforms提供了对PIL Image对象和Tensor对象的常用操作。
1)对PIL Image的常见操作如下。
·Scale/Resize:调整尺寸,长宽比保持不变。
·CenterCrop、RandomCrop、RandomSizedCrop:裁剪图片,CenterCrop和 RandomCrop在crop时是固定size,RandomResizedCrop则是random size的crop。
·Pad:填充。
·ToTensor:把一个取值范围是[0,255]的PIL.Image转换成Tensor。形状为(H,W,C)的
Numpy.ndarray转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloatTensor。 ·RandomHorizontalFlip:图像随机水平翻转,翻转概率为0.5。
·RandomVerticalFlip:图像随机垂直翻转。 ·ColorJitter:修改亮度、对比度和饱和度。
2)对Tensor的常见操作如下。
·Normalize:标准化,即,减均值,除以标准差。
·ToPILImage:将Tensor转为PIL Image。
如果要对数据集进行多个操作,可通过Compose将这些操作像管道一样拼接起来,类 似于nn.Sequential。以下为示例代码:
transforms.Compose([
#将给定的 PIL.Image 进行中心切割,得到给定的 size,
#size 可以是 tuple,(target_height, target_width)。
#size 也可以是一个 Integer,在这种情况下,切出来的图片形状是正方形。
transforms.CenterCrop(10),
#切割中心点的位置随机选取
transforms.RandomCrop(20, padding=0),
#把一个取值范围是 [0, 255] 的 PIL.Image 或者 shape 为 (H, W, C) 的 numpy.ndarray, #转换为形状为 (C, H, W),取值范围是 [0, 1] 的 torch.FloatTensor
transforms.ToTensor(),
#规范化到[-1,1]
transforms.Normalize(mean = (0.5, 0.5, 0.5), std = (0.5, 0.5, 0.5))
])
还可以自己定义一个Python Lambda表达式,如将每个像素值加10,可表示为: transforms.Lambda(lambda x:x.add(10))。
官网:https://PyTorch.org/docs/stable/torchvision/transforms.html。
2 ImageFolder
当文件依据标签处于不同文件下时。可以利用torchvision.datasets.ImageFolder来直接构造出dataset,代码如下:
loader = datasets.ImageFolder(path)
loader = data.DataLoader(dataset)
ImageFolder会将目录中的文件夹名自动转化成序列,当DataLoader载入时,标签自动 就是整数序列了。
下面我们利用ImageFolder读取不同目录下的图片数据,然后使用transforms进行图像 预处理,预处理有多个,我们用compose把这些操作拼接在一起。然后使用DataLoader加 载。
对处理后的数据用torchvision.utils中的save_image保存为一个png格式文件,然后用 Image.open打开该png文件,详细代码如下:
import torch
from torchvision import transforms,utils,datasets
import matplotlib.pyplot as plt
my_trans = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor()
])
train_data = datasets.ImageFolder('./data/torchvision_data',transforms=my_trans)
train_loader = utils.data.DataLoader(train_data,batch_size = 8,shuffle=True)
for i_batch, img in enumerate(train_loader):
if i_batch == 0:
print(img[1])
fig = plt.figure()
grid = utils.make_grid(img[0]) # 将多张图片拼接在一个网格中
plt.imshow(grid.numpy().transpose((1, 2, 0)))
plt.show()
utils.save_image(grid,'test01.png')
break
from PIL import Image
Image.open('test01.png')
4.4 可视化工具
4.4.1 tensorboardX简介
from tensorboardX import SummaryWriter
from tensorboardx import SummaryWriter
writer = SummaryWriter(log_dir = 'logs')
SummaryWriter(log_dir=None, comment='', **kwargs)
#其中comment在文件命名加上comment后缀
# 如果不写log_dir,系统将在当前目录创建一个runs的目录。
writer.add_xxX()
2)调用相应的API接口,接口一般格式为:
# add_xxx(tag-name, object, iteration-number) #即add_xxx(标签,记录的对象,迭代次数)
writer.close()
## 3)启动tensorboard服务:cd到logs目录所在的同级目录,在命令行输入如下命令,
# logdir等式右边可以是相对路 径或绝对路径。
# tensorboard --logdir=logs --port 6006 #如果是Windows环境,要注意路径解析,如
#tensorboard --logdir=r'D:\myboard\test\logs' --port 6006
# 4)web展示。在浏览器输入: http://服务器IP或名称:6006 #如果是本机,服务器名称可以使用localhost
https://github.com/lanpa/tensorboardX。
2 用tensorboardX可视化神经网络
'''用tensorboardX可视化神经网络'''
# (1)导入需要的模块
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from tensboardX import SummaryWriter
# (2)构建神经网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
self.conv2_drop = nn.Dropout2d()
self.fc1 = nn.Linear(320, 50)
self.fc2 = nn.Linear(50, 10)
self.bn = nn.BatchNorm2d(20)
def forward(self, x):
x = F.max_pool2d(self.conv1(x), 2)
x = F.relu(x) + F.relu(-x)
x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
x = self.bn(x)
x = x.view(-1, 320)
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc2(x)
x = F.softmax(x, dim=1)
return x
# (3)把模型保存为graph
#定义输入
input = torch.rand(32, 1, 28, 28)
#实例化神经网络
model = Net()
out = model(input)
print(out.shape)
#将model保存为graph
with SummaryWriter(log_dir='logs',comment='Net') as w:
w.add_graph(model, (input, ))
3 用tensorboardX可视化损失值
可视化损失值,需要使用add_scalar函数,这里利用一层全连接神经网络,训练一元
二次函数的参数。
import torch
import numpy as np
import torch.nn as nn
from tensboardX import SummaryWriter
input_size=1
output_size=1
learning_rate = 0.0001
num_epoches = 1000
dtype = torch.FloatTensor
writer = SummaryWriter(log_dir='logs',comment='Linear')
np.random.seed(100)
x_train = np.linspace(-1, 1, 100).reshape(100,1)
y_train = 3*np.power(x_train, 2) +2+ 0.2*np.random.rand(x_train.size).reshape(100,1)
model = nn.Linear(input_size, output_size)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
for epoch in range(num_epoches):
inputs = torch.from_numpy(x_train).type(dtype)
targets = torch.from_numpy(y_train).type(dtype)
output = model(inputs)
loss = criterion(output, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 保存loss的数据与epoch数值
writer.add_scalar('训练损失值', loss, epoch)
4 用tensorboardX可视化特征图
import torchvision.utils as vutils
from tensboardX import SummaryWriter
writer = SummaryWriter(log_dir='logs',comment='feature map')
img_grid = vutils.make_grid(x, normalize=True, scale_each=True, nrow=2)
net.eval()
for name, layer in net._modules.items():
# 为fc层预处理x
x = x.view(x.size(0), -1) if "fc" in name else x
print(x.size())
x = layer(x)
print(f'{name}')
# 查看卷积层的特征图
if 'layer' in name or 'conv' in name:
x1 = x.transpose(0, 1) # C,B, H, W ---> B,C, H, W
img_grid = vutils.make_grid(x1, normalize=True, scale_each=True, nrow=4) # normalize进行归一化处理
writer.add_image(f'{name}_feature_maps', img_grid, global_step=0)
5 机器学习
- 选择模型及损失函数
二分类、单标签 有sigmoid nn.BCELoss
二分类、单标签 无sigmoid nn.BCEWithLogistsLoss
二分类、多标签 无激活函数 nn.SoftMarginLoss(target 1/-1)
多分类、单标签 无softmax nn.CrossEntropyLoss(target 为one_hot)
多分类、单标签 有softmax nn.NLLLoss
多分类、多标签 无激活函数 nn.MultiLabelSoftMarginLoss
- 评估及优化模型
·留出法(Holdout):留出法的步骤相对简单,直接将数据集划分为两个互斥的集 合,其中一个集合作为训练集,另一个作为测试集。在训练集上训练出模型后,用测试集 来评估测试误差,作为泛化误差的估计。使用留出法,还可以优化出一种更好的方法,就 是把数据分成3部分:训练数据集、验证数据集、测试数据集。训练数据集用来训练模 型,验证数据集用来调优超参数,测试集则用来测试模型的泛化能力。数据量较大时可采 用这种方法。
·K折交叉验证:不重复地随机将训练数据集划分为k个,其中k-1个用于模型训练,剩 余的一个用于测试。
·重复的K折交叉验证:当数据量比较小,数据分布不很均匀时可以采用这种方法。
6 视觉处理基础
- ·卷积神经网络简介。
- ·卷积定义。
- ·卷积运算。
- ·卷积层。
- ·池化层。
- ·现代经典网络架构。
- ·实例:用TensorFlow实现一个卷积神经网络。
- LeNet-5模型
LeCun提出的LeNet,系统地提出了卷积层、池化层、全连 接层等概念.
LeNet-5模型结构为输入层-卷积层-池化层-卷积层-池化层-全连接层-全连接层-输出。
(2)模型特点
·每个卷积层包含3个部分:卷积、池化和非线性激活函数。
·使用卷积提取空间特征。
·采用降采样(Subsample)的平均池化层(Average Pooling)。
·使用双曲正切(Tanh)的激活函数。 ·最后用MLP作为分类器。
- AlexNet模型
AlexNet,提出一些训练深度网络的重要方 法或技巧,如Dropout、ReLu、GPU、数据增强方法等
AlexNet为8层深度网络,其中5层卷积层和3层全连接层,不计LRN层和池化层。
·由5层卷积和3层全连接组成,输入图像为3通道224×224大小,网络规模远大于
LeNet。
·使用ReLU激活函数。
·使用Dropout,可以作为正则项防止过拟合,提升模型鲁棒性。
·具备一些很好的训练技巧,包括数据增广、学习率策略、Weight Decay等。
- VGG模型
VGG可以看成是加深版本的AlexNet.都是 Conv Layer+FC layer,在当时看来这是一个非常深的网络了,层数高达16或19层。
- GoogleNet模型
GG是增加网络的深度,但深度达到一个程度时,可能就成为瓶颈。GoogLeNet则从 另一个维度来增加网络能力,每单元有许多层并行计算,让网络更宽了。
模型特点
1)引入Inception结构,这是一种网中网(Network In Network)的结构。 通过网络的水平排布,可以用较浅的网络得到较好的模型能力,并进行多特征融合,
同时更容易训练。另外,为了减少计算量,使用了1×1卷积来先对特征通道进行降维。
2)采用全局平均池化层。
将后面的全连接层全部替换为简单的全局平均池化,在最后参数会变得更少。GoogleNet移除全连接层,但并不会影响到结果的精度,在ImageNet中实现93.3%的精 度,而且要比VGG还快。
- ResNet模型
模型特点:
·层数非常深,已经超过百层。
·引入残差单元来解决退化问题。
- 显示参数:
import collections
import torch
import torch.nn as nn
def paras_summary(input_size, model):
def register_hook(module):
def hook(module, input, output):
class_name = str(module.__class__).split('.')[-1].split("'")[0]
module_idx = len(summary)
m_key = '%s-%i' % (class_name, module_idx+1)
summary[m_key] = collections.OrderedDict()
summary[m_key]['input_shape'] = list(input[0].size())
summary[m_key]['input_shape'][0] = -1
summary[m_key]['output_shape'] = list(output.size())
summary[m_key]['output_shape'][0] = -1
params = 0
if hasattr(module, 'weight'):
params += torch.prod(torch.LongTensor(list(module.weight.size())))
if module.weight.requires_grad:
summary[m_key]['trainable'] = True
else:
summary[m_key]['trainable'] = False
if hasattr(module, 'bias'):
params += torch.prod(torch.LongTensor(list(module.bias.size())))
summary[m_key]['nb_params'] = params
if not isinstance(module, nn.Sequential) and \
not isinstance(module, nn.ModuleList) and \
not (module == model):
hooks.append(module.register_forward_hook(hook))
# check if there are multiple inputs to the network
if isinstance(input_size[0], (list, tuple)):
x = [torch.rand(1,*in_size) for in_size in input_size]
else:
x = torch.rand(1,*input_size)
# create properties
summary = collections.OrderedDict()
hooks = []
# register hook
model.apply(register_hook)
# make a forward pass
model(x)
# remove these hooks
for h in hooks:
h.remove()
return summary
import torch.nn as nn
import torch.nn.functional as F
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 16, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(16, 36, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.pool2 = nn.MaxPool2d(2, 2) #使用全局平均池化层
self.aap=nn.AdaptiveAvgPool2d(1)
self.fc3 = nn.Linear(36, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = self.aap(x)
x = x.view(x.shape[0], -1)
x = self.fc3(x)
return x
net = Net()
net=net.to(device)
if __name__=='__main__':
net = Net() #输入格式为[c,h,w]即通道数,图像的高级宽度
input_size=[3,32,32]
pa = paras_summary(input_size,net)
for i ,j in zip(pa.keys(),pa.values()):
print(f'k: {i},v:{j}')
- 集成效果
mlps=[net1.to(device),net2.to(device),net3.to(device)]
optimizer=torch.optim.Adam([{"params":mlp.parameters()} for mlp in mlps],lr=LR)
loss_function=nn.CrossEntropyLoss()
for ep in range(EPOCHES):
for img,label in trainloader:
img,label=img.to(device),label.to(device) optimizer.zero_grad()#10个网络清除梯度
for mlp in mlps:
mlp.train()
out=mlp(img) loss=loss_function(out,label) loss.backward()#网络获得的梯度
optimizer.step()
pre=[]
vote_correct=0
mlps_correct=[0 for i in range(len(mlps))]
for img,label in testloader:
img,label=img.to(device),label.to(device)
for i, mlp in enumerate( mlps):
mlp.eval()
out=mlp(img)
_,prediction=torch.max(out,1) #按行取最大值 pre_num=prediction.cpu().numpy() mlps_correct[i]+=(pre_num==label.cpu().numpy()).sum()
pre.append(pre_num)
arr=np.array(pre)
pre.clear()
result=[Counter(arr[:,i]).most_common(1)[0][0] for i in range(BATCHSIZE)]
vote_correct+=(result == label.cpu().numpy()).sum()
print("epoch:" + str(ep)+"集成模型的正确率"+str(vote_correct/len(testloader)))
for idx, coreect in enumerate( mlps_correct):
print("模型"+str(idx)+"的正确率为:"+str(coreect/len(testloader)))
6 相关的数学知识
- 标量Scalar:单独的一个数,维数为0。
- 向量Vector:一列按顺序排列的元素,维数为1。
- 矩阵Matrix:二维数组结构,用大写字母来表示。
- 张量Tensor: 数组的维度超过了二维的高维数组。
import numpy as np
scalar = np.array(3)
vector = np.array([1,2,3])
matrix = np.arange(9).reshape(3,3)
tensor = np.arange(24).reshape(2,3,4)
print(' shape ',' ndim ')
print(scalar.shape,' ',scalar.ndim)
print(vector.shape,' ',vector.ndim)
print(matrix.shape,' ',matrix.ndim)
print(tensor.shape,'',tensor.ndim)
'''
shape ndim
() 0
(3,) 1
(3, 3) 2
(2, 3, 4) 3
'''
- 矩阵的转置
a = np.random.randint(0,10,[3,4])
c = np.zeros_like(a.T)
print('a:\n',a)
print('c: \n',c)
for i in range(c.shape[0]):
for j in range(c.shape[1]):
c[i,j]= a[j,i]
print('a.T: \n',c)
'''
a:
[[4 1 0 5]
[2 8 5 6]
[9 9 6 5]]
c:
[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]
a.T:
[[4 2 9]
[1 8 9]
[0 5 6]
[5 6 5]]
'''
- 矩阵加减乘
import numpy as np
a = np.random.randint(0,10,[3,4])
b = np.random.randint(0,10,[5,3])
def add(a,b):
assert a.shape==b.shape
h,w = a.shape
c = np.zeros([h,w])
for i in range(h):
for j in range(w):
c[i,j] = a[i,j]+b[i,j]
return c
def sub(a,b):
assert a.shape==b.shape
h,w = a.shape
c = np.zeros([h,w])
for i in range(h):
for j in range(w):
c[i,j] = a[i,j]-b[i,j]
return c
def mal(a,b):
assert a.shape==b.shape
h,w = a.shape
c = np.zeros([h,w])
for i in range(h):
for j in range(w):
c[i,j] = a[i,j]*b[i,j]
return c
def matrix(a,b):
assert a.shape[1]==b.shape[0]
h,w = a.shape[0],b.shape[1]
c = np.zeros([h,w])
for i in range(h):
for j in range(w):
for k in range(a.shape[1]):
c[i,j] += a[i,k]*b[k,j]
return c
if __name__ =='__main__':
a = np.random.randint(0,10,[3,4])
b = np.random.randint(0,10,a.shape)
print('a:\n',a)
print('b:\n',b)
print('a+b:\n',add(a,b))
print('a-b:\n',sub(a,b))
print('a·b:\n',mal(a,b))
print('a*b:\n',matrix(a,b.T))
'''
a:
[[1 0 1 8]
[3 6 1 8]
[4 9 0 8]]
b:
[[3 3 9 7]
[5 1 6 6]
[8 6 3 9]]
a+b:
[[ 4. 3. 10. 15.]
[ 8. 7. 7. 14.]
[12. 15. 3. 17.]]
a-b:
[[-2. -3. -8. 1.]
[-2. 5. -5. 2.]
[-4. 3. -3. -1.]]
a·b:
[[ 3. 0. 9. 56.]
[15. 6. 6. 48.]
[32. 54. 0. 72.]]
a*b:
[[ 68. 59. 83.]
[ 92. 75. 135.]
[ 95. 77. 158.]]
'''
- 激活函数
import numpy as np
def sigmoid(x):
return 1./(1.+np.exp(-x))
def tanh(x):
return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
def ReLU(x):
return np.maximum(0,x)
def LeakReLU(x,a):
return np.where(x>=0,np.maximum(0,x),a*x)
if __name__ =='__main__':
np.random.seed(1024)
x = np.random.randn(6)
print(sigmoid(x))
print(tanh(x))
print(ReLU(x))
print(LeakReLU(x,a=0.1))
'''
[0.89325684 0.5628277 0.81064072 0.63858774 0.61259269 0.30803255]
[ 0.97184215 0.24740444 0.89651607 0.51480076 0.42863533 -0.66922239]
[2.12444863 0.25264613 1.45417876 0.56923979 0.45822365 0. ]
[ 2.12444863 0.25264613 1.45417876 0.56923979 0.45822365 -0.08093334]
'''
(1) 自动求导
from torch import nn
import torch
import torch.nn.functional as F
from torch.autograd import Variable
if __name__=='__main__':
batch_n = 100
input_data = 1000
hidden_layer = 100
output_data = 10
epoch_n = 10001
learning_rate = 1e-6
x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(hidden_layer,output_data),requires_grad=False)
w1 = Variable(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = Variable(torch.randn(hidden_layer,output_data),requires_grad=True)
for epoch in range(epoch_n):
y_pred = x.mm(w1).clamp(min=0).mm(w2)
loss = (y_pred-y).pow(2).sum()
if epoch%500==0:
print('Epoch:{}, Loss:{:.4f}'.format(epoch,loss.data))
loss.backward()
w1.data -= learning_rate*w1.grad.data
w2.data -= learning_rate*w2.grad.data
w1.grad.data.zero_()
w2.grad.data.zero_()
'''
Epoch:0, Loss:46297568.0000
Epoch:500, Loss:2064.5229
Epoch:1000, Loss:332.0856
Epoch:1500, Loss:92.1883
Epoch:2000, Loss:34.2231
Epoch:2500, Loss:15.4424
Epoch:3000, Loss:8.0198
Epoch:3500, Loss:4.5941
Epoch:4000, Loss:2.8243
Epoch:4500, Loss:1.8257
Epoch:5000, Loss:1.2236
Epoch:5500, Loss:0.8433
Epoch:6000, Loss:0.5939
Epoch:6500, Loss:0.4257
Epoch:7000, Loss:0.3103
Epoch:7500, Loss:0.2297
Epoch:8000, Loss:0.1725
Epoch:8500, Loss:0.1313
Epoch:9000, Loss:0.1013
Epoch:9500, Loss:0.0791
Epoch:10000, Loss:0.0625
Process finished with exit code 0
'''
(2) 自定义传播函数
from torch import nn
import torch
import torch.nn.functional as F
from torch.autograd import Variable
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
def forward(self, input, w1, w2):
x = torch.mm(input ,w1)
x = torch.clamp(x,min=0)
x = torch.mm(x,w2)
return x
if __name__=='__main__':
batch_n = 100
input_data = 1000
hidden_layer = 100
output_data = 10
epoch_n = 10001
learning_rate = 1e-6
x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(hidden_layer,output_data),requires_grad=False)
w1 = Variable(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = Variable(torch.randn(hidden_layer,output_data),requires_grad=True)
for epoch in range(epoch_n):
y_pred = Model()(x,w1,w2)
loss = (y_pred-y).pow(2).sum()
if epoch%500==0:
print('Epoch:{}, Loss:{:.4f}'.format(epoch,loss.data))
loss.backward()
w1.data -= learning_rate*w1.grad.data
w2.data -= learning_rate*w2.grad.data
w1.grad.data.zero_()
w2.grad.data.zero_()
'''
Epoch:0, Loss:45101876.0000
Epoch:500, Loss:2105.3201
Epoch:1000, Loss:351.6454
Epoch:1500, Loss:115.2642
Epoch:2000, Loss:53.0504
Epoch:2500, Loss:30.2131
Epoch:3000, Loss:19.8175
Epoch:3500, Loss:14.4892
Epoch:4000, Loss:11.3584
Epoch:4500, Loss:9.3450
Epoch:5000, Loss:7.9523
Epoch:5500, Loss:6.9340
Epoch:6000, Loss:6.1545
Epoch:6500, Loss:5.5373
Epoch:7000, Loss:5.0327
Epoch:7500, Loss:4.6104
Epoch:8000, Loss:4.2507
Epoch:8500, Loss:3.9397
Epoch:9000, Loss:3.6656
Epoch:9500, Loss:3.4207
Epoch:10000, Loss:3.1994
Process finished with exit code 0
'''
(3) optimizer
from torch import nn
import torch
import torch.nn.functional as F
from torch.autograd import Variable
class Model(torch.nn.Module):
def __init__(self,input_data,hidden_layer,output_data):
super(Model, self).__init__()
self.model = torch.nn.Sequential(nn.Linear(input_data,hidden_layer),
nn.ReLU(),
nn.Linear(hidden_layer,output_data))
def forward(self, x):
x = self.model(x)
return x
if __name__=='__main__':
batch_n = 100
input_data = 1000
hidden_layer = 100
output_data = 10
epoch_n = 1001
learning_rate = 1e-6
x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(hidden_layer,output_data),requires_grad=False)
model = Model(input_data,hidden_layer,output_data)
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(),lr= learning_rate)
for epoch in range(epoch_n):
y_pred = model(x)
loss = loss_fn (y_pred,y)
if epoch%500==0:
print('Epoch:{}, Loss:{:.4f}'.format(epoch,loss.data))
optimizer.zero_grad()
loss.backward()
optimizer.step()
'''
Epoch:0, Loss:1.1027
Epoch:500, Loss:0.9990
Epoch:1000, Loss:0.9066
Process finished with exit code 0
'''
(4) No optimizer
from torch import nn
import torch
import torch.nn.functional as F
from torch.autograd import Variable
class Model(torch.nn.Module):
def __init__(self,input_data,hidden_layer,output_data):
super(Model, self).__init__()
self.model = torch.nn.Sequential(nn.Linear(input_data,hidden_layer),
nn.ReLU(),
nn.Linear(hidden_layer,output_data))
def forward(self, x):
x = self.model(x)
return x
if __name__=='__main__':
batch_n = 100
input_data = 1000
hidden_layer = 100
output_data = 10
epoch_n = 1001
learning_rate = 1e-6
x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(hidden_layer,output_data),requires_grad=False)
model = Model(input_data,hidden_layer,output_data)
loss_fn = torch.nn.MSELoss()
for epoch in range(epoch_n):
y_pred = model(x)
loss = loss_fn (y_pred,y)
if epoch%500==0:
print('Epoch:{}, Loss:{:.4f}'.format(epoch,loss.data))
model.zero_grad()
loss.backward()
for param in model.parameters():
param.data -= learning_rate * param.grad.data
'''
Epoch:0, Loss:1.0688
Epoch:500, Loss:1.0684
Epoch:1000, Loss:1.0680
Process finished with exit code 0
'''