首先谢谢刘老师的视频课,我没有白嫖,我点赞投币了,哈哈哈哈,刘老师讲的很好,感谢,同时感谢吴恩达老师的深度学习的课程,很随和、亲和。谢谢
还要谢谢CSDN博主(大佬):错错莫、whut_L、LoveMIss-Y。学习刘老师代码,经常翻看三位大佬的博客,学到很多。谢谢
书写以做记录,自己打的注释,有很多代码没有打清楚,也没有打对,所以仅自己参考,不喜勿喷,写错的请路过的大佬指出来,非常感谢。
是根据刘老师的视频复刻的代码。里面自己也有很多不懂的。
里面的逻辑、流程、还有一些个别的代码,的注释,包括最后的RNN中的GRU模型的代码注释,自己还是打的不太好。后面自己会补上的,不过要好久了。大家可以帮忙纠错,谢谢。一起学习。
废话:
里面还有很多不懂的地方,自己感觉pytorch书写,是把模型用代码的形式表现出来,个人感觉最难的是参数的设置环节,对pytorch中的模型的参数弄明白了,基本上就懂得差不多了,还有一个就是整体的流程,代码实现的哪一个流程。怎么说呢,代码是没有咱们人这么舒坦(不会用词了),心里有想法,但是用代码可能需要提前准备很多,虽然已经很简便了,但是对于咱们看数学公式,个人感觉还是比较麻烦的,所以自己代码能力还是有待提高。
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
import matplotlib.pyplot as plt
"""
数据:特征、标签;设置权值:(0,4,0.01)-特征值和不同的w进行变换,
根据损失函数,输出。
"""
#数据集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
def forward(x):
"""
特征经过网络进行变换得到预测
特征乘权重;
:param x: 输入
:return: x * w;
"""
return x * w
def loss(x, y):
"""
求得预测与真实的误差
:param x: 特征
:param y: 真实值
:return: 损失
"""
y_pred = forward(x)
return (y_pred - y) * (y_pred - y)
#创建两个空列表;分别用于存放每一次权重值 和 每一次循环的 误差
w_list = []
mes_list = []
for w in np.arange(0.0, 4.1, 0.01):
"""
进行了0.0-4.1距离;间隔0.01;次循环;进行循环
损失和,初始化
取特征集和对应的标签传给x_val,y_val,
调用forward函数返回y_pred_val预测值;
调用loss函数返回loss_val损失值
求损失的和
输出
"""
# print('w = ', w)
l_sum = 0
for x_val, y_val in zip(x_data, y_data):
y_pred_val = forward(x_val)
loss_val = loss(x_val, y_val)
l_sum += loss_val
print('\t', x_val, y_val, y_pred_val, loss_val)
print('MSE = ', l_sum / 3)
w_list.append(w)
mes_list.append(l_sum / 3)
#画图:每一次的w为x轴;对应的误差为y轴
plt.plot(w_list, mes_list)
plt.ylabel('Loss')
plt.plot('w')
plt.show()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#创建数据集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
def forward(x):
"""
返回的是预测值
:param x: 输入
:return: 经过网络的输出
"""
return x * w + b
def loss(x, y):
"""
返回的是预测值与真实值得平方差
:param x: 特征
:param y: 预测值
:return: 误差
"""
y_pred = forward(x)
return (y_pred - y) ** 2
#创建列表用于存放w值;损失值;偏执值
# w_list = []
mes_list = []
# b_list = []
W = np.arange(0.0, 4.1, 0.01)
B = np.arange(0.0, 4.1, 0.01)
[w, b] = np.meshgrid(W, B)
"""
#zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
"""
l_sum = 0
for x_val, y_val in zip(x_data, y_data):
y_pred_val = forward(x_val)
loss_val = loss(x_val, y_val)
l_sum += loss_val
# print(x_val, y_val, loss_val)
# b_list.append(b)
# print('MSE:', l_sum / 3)
# w_list.append(w)
# mes_list.append(l_sum / 3)
#画图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(w, b, l_sum/3)
plt.show()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1.0
def forward(x):
return x * w
def cost(xs, ys):
"""
:param xs: 特征
:param ys: 对应的真实值
:return: 误差;返回的均方误差
"""
cost = 0
for x, y in zip(xs, ys):
y_pred = forward(x)
cost += (y_pred - y) ** 2
return cost / len(xs)
def gradient(xs, ys):
"""
求导(误差求导)
:param xs: 特征
:param ys: 对应的真实值
:return: 返回的是均方误差的导数
"""
grad = 0
for x, y in zip(xs, ys):
grad += 2 * x * (x * w - y)
return grad / len(xs)
print('Predict (before traning)', 4, forward(4))
for epoch in range(100):
"""
遍历100次
调用cost函数计算损失值即误差值
调用gradient函数求得求导值
更新w值
输出第几次迭代,对应的更新的权值,损失值
"""
cost_val = cost(x_data, y_data)
grad_val = gradient(x_data, y_data)
w -= 0.01 * grad_val
print('Epoch:', epoch, 'w = ', w, 'loss = ', cost_val)
print('Predict (after training)', 4, forward(4))
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1.0
def forward(x):
return x * w
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
def gradient(x, y):
return 2 * x * (x * w - y)
"""
#第一次更新w前,使用w=1.0对特征为4时进行预测,返回预测值
#第二次,更新w后,使用更新后的w,对特征为4时预测,返回预测值
"""
print('Predict (before traning)', 4, forward(4))
for epoch in range(100):
for x, y in zip(x_data, y_data):
"""
求梯度
更新w
输出特征和对应的真实标签;
计算损失
输出w和loss
"""
grad = gradient(x, y)
w -= 0.01 * grad
print('\tgrad:', x, y, grad)
l = loss(x, y)
print('progress:', epoch, 'w = ', w, 'loss = ', l)
print('Predict (after training)', 4, forward(4))
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = torch.Tensor([1.0])
w.requires_grad = True
"""
因为torch.Tensor函数,所以我们的w是一个张量;
下面我们计算时,返回的也是张量;这样就可以有一其他功能,便可直接函数取出我们想要的值;
item()是从原来的精度上更加精确;
最外的两个print分别是,模型跑之前,和w值改变之后再跑的预测结果。
"""
def forward(x):
return x * w
def loss(x, y):
"""
:param x: 输入特征
:param y: 真实值
:return: 损失值即误差
"""
y_pred = forward(x)
return (y_pred - y) ** 2
print("predict (before training)", 4, forward(4).item())
for epoch in range(100):
for x, y in zip(x_data, y_data):
"""
调用loss函数,求损失函数
l.backward()--反向传播函数,自动会计算并且w的值也会做相应的更新,并且最终会释放掉数据
这个函数作用就是用于做反向循环--这个时候w的值会有两个:w.data--w的值、w.grad--梯度值即对误差求导的值;
更新w.data
w.grad清零,即释放,用于下次计算
"""
l = loss(x, y)
l.backward()
print('\tgrad:', x, y, w.grad.item(), w.data)
w.data = w.data - 0.01 * w.grad.data
print(w.data)
w.grad.data.zero_()
print(w.data, w.grad.item())
print('progress:', epoch, l.item())
print('predict (after taining)', 4, forward(4).item())
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[2.0], [4.0], [6.0]])
class LinearModel(torch.nn.Module):
"""
模型继承:linear模型
linear(1, 1)是特征和输出的维度为一维
forward:构建模型中的各个层的关系---也是输出怎么到输出的,用到哪些层;---可以调用__init__里的函数
__init__:通多调用nn.Module中函数进行搭建每一层所用到的函数,函数的参数
forward:将__init__中的搭建好的函数连通起来,告诉我们怎么连通,叙述整个流程
"""
def __init__(self):
super(LinearModel, self).__init__()
self.linear = torch.nn.Linear(1, 1) # w, b
def forward(self, x):
y_pred = self.linear(x)
return y_pred
"""
模型的实例化
调用损失函数--criterion
选择优化器,学习率设置为0.01;同时其他的值通过model.parameters()函数进行初始化。
里面自己有各种参数,权重 偏置
"""
model = LinearModel()
criterion = torch.nn.MSELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(1000):
"""
迭代1000次;
模型传入特征值--返回预测值y_pred
往损失函数-criterion-中传入预测值和真实值--返回损失值loss
输出 当前迭代次数 + 当前损失值
通过zero_grad函数将梯度值(即损失函数的导数)设置为0
.backward进行反向传播
optimizer.step()进行权值w和偏置b的迭代
"""
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
"""
输出最后的权值w
输出最后的偏置b
设置测试集数据
将测试集放入模型中进行预测
通过.data 输出预测数据
"""
print('w = ', model.linear.weight.item())
print('b = ', model.linear.bias.item())
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as plt
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[0], [0], [1]])
class LogisticRegressionModel(torch.nn.Module):
"""
继承nn.Module中的逻辑回归函数类
linear(1, 1)--特征和标签都是一维数据
"""
def __init__(self):
super(LogisticRegressionModel, self).__init__()
self.linear = torch.nn.Linear(1, 1)
def forward(self, x):
"""
先通过linear函数进行求得预测值
然后通过调用F(torch.nn.functional)包中的sigmoid函数对预测结果达到分类效果
:param x:特征
:return: 分类标准(0, 1)用到的是sigmoid函数
"""
y_pred = F.sigmoid(self.linear(x))
return y_pred
"""
模型实例化
调用函数使用BCELoss求损失,并传给criterion
对模型参数w和b进行初始化;学习率设置为0.01
"""
model = LogisticRegressionModel()
criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(1000):
"""
遍历1000次
将数据存入模型返回预测值y_pred
使用函数criterion,并传入预测值和对应的真实值;求得损失函数
输出 当前迭代次数 和 损失值的高精度数据
优化器的梯度赋值为0 即损失函数的导数
通过backward函数进行反向传播
使用optimizer.step()函数进行更新权值和偏置
"""
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
"""
取0-10中200个点 赋值给x
将数组x变成张量 -- x_t
将张量x_t放入模型,得到预测张量y_t
利用y_t.data函数,取出预测值,变成数组形式 返回给y
画图传入参数x,y (两个数据都是数组类型,并且长度是一样的)
画一条平行于x轴的红线。即[0, 10], [0.5, 0.5], c='r'
输出图像plot.show()
"""
x = np.linspace(0, 10, 200)
x_t = torch.Tensor(x).view((200, 1))
y_t = model(x_t)
y = y_t.data.numpy()
plt.plot(x, y)
plt.plot([0, 10], [0.5, 0.5], c='r')
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()
plt.show()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
import matplotlib.pyplot as py
import torch
"""
读取文件,以逗号未分割点
取所有行,和第一列到倒数第二列
取所有行,和最后一列
"""
xy = np.loadtxt('diabetes.csv', delimiter=',', dtype=np.float32)
x_data = torch.from_numpy(xy[:, :-1])
y_data = torch.from_numpy(xy[:, [-1]])
class Model(torch.nn.Module):
"""
super继承Module库
线性变换;
8维指的是8个特征-6维是6个特征;8个权重-6个权重
这是线性网络
输入数据为8维-输出6维
输入数据为6维-输出4维
输入数据为4维-输出1维
调用sigmoid函数,对数据判断
"""
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
"""
:param x:输入数据
:return:预测值
"""
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
"""
模型实例化
调用BCELoss函数--给criterion函数
使用SGD优化器,模型参数初始化(parameters()),学习率为0.01
"""
model = Model()
criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
"""
遍历100次
将特征值传入模型,返回预测值(张量)
传入预测和真实值,通过criterion函数,返回损失函数
输出 当前次数 和 损失函数的高精度
优化器中梯度值 参数归零
反向传播
通过优化器函数,optimizer.step函数进行更新权值w和偏置b,以及梯度值
"""
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
class DiabetesDataset(Dataset):
"""
DiabetesDataset类继承Dataset类
重写__init__方法:
文件读取,传给xy
去xy的shape[0],即取数据的数量,也即有多少行
通过torch模块中的from_numpy函数进行数据的读取操作
返回的 x_data y_data 都是张量
重写__getitem__方法:
返回x_data的索引 和 y_data的索引
重写__len__方法:
返回数据第一位的数值
"""
def __init__(self, filepath):
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
self.len = xy.shape[0]
self.x_data = torch.from_numpy(xy[:, :-1])
self.y_data = torch.from_numpy(xy[:, [-1]])
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
def __len__(self):
return self.len
"""
读取文件diabetes文件;返回dataset
通过DataLoader函数,传入参数:数据集,单词训练的样本数量;是否打乱数据集,多线程工作
"""
dataset = DiabetesDataset('diabetes.csv')
train_loader = DataLoader(dataset=dataset,
batch_size=32,
shuffle=True,
num_workers=2)
class Model(torch.nn.Module):
"""
继承Module类,
搭建不同层数中权值参数维度的变化。
搭建一个sigmoid函数
都是用torch库中封装好的函数
"""
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
"""
:param x: 特征
:return: 预测数据
"""
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
"""
模型实例化--model
调用BCELoss损失函数
选择SGD优化器,其中初始化模型参数,学习率设置为0.01
"""
model = Model()
criterion = torch.nn.BCELoss(size_average=True)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
if __name__ == '__main__':
for epoch in range(100):
for i, data in enumerate(train_loader, 0):
"""
i:第几次循环;
data:【张量每个数据集,张量每个数据对应的标签】
张量每个数据集:一个列表,batch个元素;每个元素是由一条数据中的特征所构成的列表。
张量每个数据对应的标签:一个列表,batch个元素,每个元素是由数据中的标签构成的列表。
[tensor([[], [], []]), tensor([[], [], []])]
"""
# print("i", i)
# print("data", data)
inputs, labels = data
"""
传出列表中的两个元素,都是张量
inputs:tensor([[], [], []])
labels:tensor([[], [], []])
"""
# print("inputs", inputs)
# print("labels", labels)
"""
将数据集传入模型,得到预测值的张量形式
通过criterion函数返回损失值--loss-张量
输出:第几次循环所有数据集,当前循环下,训练的第几组(一个batch长度为一组)的数据集,和相应的损失值的高精度格式
梯度值清零
反向传播
利用优化器进行参数更新
"""
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
train_dataset = datasets.MNIST(root='../dataset/mnist',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = datasets.MNIST(root='../dataset/mnist',
train=False,
transform=transforms.ToTensor(),
download=True)
train_loader = DataLoader(dataset=train_dataset,
batch_size=32,
shuffle=True)
test_loader = DataLoader(dataset=test_dataset,
batch_size=32,
shuffle=False)
for batch_idx, (inputs, target) in enumerate(train_loader):
pass
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import numpy as np
y = np.array([1, 0, 0])
z = np.array([0.2, 0.1, -0.1])
y_pred = np.exp(z) / np.exp(z).sum()
loss = (-y * np.log(y_pred)).sum()
print(loss)
"""
这个是实现:我们给出真实的标签,和我们最后的输出层的数据;然后我们通过后softmax函数进行变换
softmax函数:e的x次方除以e的x次方的和,这个时候我们就可以保证每一个值是可以实现总和等于1的
同时我们就可以计算损失函数 -[ylog(y_^) + (1 - y)log(1 - y_^)]
我们可以直接写成 -ylog(y_^)
"""
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
y = torch.LongTensor([0])
z = torch.Tensor([[0.2, 0.1, -0.1]])
criterion = torch.nn.CrossEntropyLoss()
loss = criterion(z, y)
print(loss)
"""
Torch.nn.CrossEntropyLoss()
交叉验证熵求解
torch直接封装好了,我们直接用,但是我们需要把数据改为张量(tensor)
封装的包括:softmax 函数:(各个数据的:e^x / sum(e^x)); 然后进行log变换,同时进行 loss函数(-ylogy_^)的求解
把后面的步骤都写出来了
所以我们的数据只需计算到最后一层,不需要进行softmax计算就好,
"""
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
criterion = torch.nn.CrossEntropyLoss()
Y = torch.LongTensor([2, 0, 1])
Y_pred1 = torch.Tensor([[0.1, 0.2, 0.9],
[1.1, 0.1, 0.2],
[0.2, 2.1, 0.1]])
Y_pred2 = torch.Tensor([[0.8, 0.2, 0.3],
[0.2, 0.3, 0.5],
[0.2, 0.2, 0.5]])
l1 = criterion(Y_pred1, Y)
l2 = criterion(Y_pred2, Y)
print("Batch Loss1 = ", l1.data, "\nBatch Loss2 = ", l2.data)
"""
两组数据我们通过【2, 0, 1】进行比较预测两组数据那个损失函数比较低
"""
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
"""
一次性组合64个数据为一个数据
对数据进行下载;
shuffle(数据是否打乱)
对数据进行打乱---在进行batch分割---train_dataset--train_loader
对数据直接进行分割 --- test_dataset--test_loader
"""
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307, ), (0.3081, ))
])
train_dataset = datasets.MNIST(root='../dataset/mnist/',
train=True,
download=True,
transform=transform)
train_loader = DataLoader(train_dataset,
shuffle=True,
batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist/',
train=False,
download=True,
transform=transform)
test_loader = DataLoader(test_dataset,
shuffle=False,
batch_size=batch_size)
class Net(torch.nn.Module):
"""
继承Module类,重写__init__和forward方法‘
继承Net类
书写神经网络层:(线性层)
forward函数书写每一层的连接状态,进行的什么变化
"""
def __init__(self):
super(Net, self).__init__()
self.l1 = torch.nn.Linear(784, 512)
self.l2 = torch.nn.Linear(512, 256)
self.l3 = torch.nn.Linear(256, 128)
self.l4 = torch.nn.Linear(128, 64)
self.l5 = torch.nn.Linear(64, 10)
def forward(self, x):
x = x.view(-1, 784)
x = F.relu(self.l1(x))
x = F.relu(self.l2(x))
x = F.relu(self.l3(x))
x = F.relu(self.l4(x))
return self.l5(x)
"""
类的实例化--model
判断使用gpu还是cpu
模型传到gpu上(.to(device))
调用损失函数--criterion
选用优化器SGD 模型的数值初始化(权值,偏置,梯度函数等等),学习率设置为0.01,
一般,神经网络在更新权值时,采用如下公式:
w = w - learning_rate * dw
引入momentum后,采用如下公式:
v = mu * v - learning_rate * dw
w = w + v
其中,v初始化为0,mu是设定的一个超变量,最常见的设定值是0.9。可以这样理解上式:如果上次的momentum()与这次的
"""
model = Net()
# model = model.cuda()
device = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
def train(epoch):
"""
损失为0.0
:param epoch: 迭代次数
:return: 训练模型
"""
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
"""
取一个batch数据的索引值和相应的数据
data = 特征数据 + 标签
将数据上传到gpu上
优化器将梯度设置为0
将特征放入模型
利用criterion函数计算损失函数
利用.backward函数进行反向传播
利用优化器进行更新权值和偏置值,更新的效果
将损失函数的高精度进行叠加,传给running_loss变量
判断对所有数据进行的第几组batch,如果是300组则输出....
并且running损失为0
"""
inputs, target = data
# inputs.cuda()
# target.cuda()
inputs, target = inputs.to(device), target.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
running_loss = 0.0
def test():
"""
:return:预测结果
定义两个变量
"""
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
"""
取出测试数据
将特征传给-images;标签传给-labels
将数据放在gpu上
将特征数据放入模型
torch.max的返回值有两个,第一个是每一行的最大值是多少,第二个是每一行最大值的下标(索引)是多少。
# dim = 1 列是第0个维度,行是第1个维度
---返回标签---
如果预测值和标签一样,则加一
total = 数据量
# 张量之间的比较运算
正确数据量除以总数据量 乘以 100 得到百分比
"""
images, labels = data
# images.cuda()
# labels.cuda()
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on test set: %d %%' % (100 * correct / total))
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
in_channels, out_channels = 5, 10
width, height = 100, 100
kernel_size = 3
batch_size = 1
"""
通道---可以想想成厚度
输入数据的设置:
batch_size = 一次集合多少数据
输入通道数
数据平面的维度,宽和高
构建卷积层:
利用卷积核进行卷积操作:nn.Conv2d :
输入通道,输出通道 卷积核的大小,就卷积核的平面层;
"""
input = torch.randn(batch_size,
in_channels,
width,
height)
conv_layer = torch.nn.Conv2d(in_channels,
out_channels,
kernel_size=kernel_size)
output = conv_layer(input)
print(input.shape)
print(output.shape)
print(conv_layer.weight.shape)
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
input = [3, 4, 6, 5, 7,
2, 4, 6, 8, 2,
1, 6, 7, 8, 4,
9, 7, 4, 6, 2,
3, 7, 5, 4, 1]
"""
(1, 1, 5, 5)--- batch, 通道, width,height
卷积核:输入通道, 输出通道, 卷积核3*3, padding = 1, 不设置偏置
重写卷积核参数
数据训练
"""
input = torch.Tensor(input).view(1, 1, 5, 5)
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1, bias=False)
kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3)
conv_layer.weight.data = kernel.data
output = conv_layer(input)
print(output)
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
"""
数据转换:batch,channel,width,height
卷积核2*2,MaxPool2d函数
搭建模型
"""
input = [3, 4, 6, 5,
2, 4, 6, 8,
1, 6, 7, 8,
9, 7, 4, 6,
]
input = torch.Tensor(input).view(1, 1, 4, 4)
maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)
output = maxpooling_layer(input)
print(output)
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
"""
batch=64;
数据转换函数--变张量
下载数据,取出训练数据,dataset.MNIST函数
数据打断设置batch,DataLoader
下载数据,取出测试数据,dataset.MNIST函数
数据不打断 设置batch
"""
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307, ), (0.3081, ))
])
train_dataset = datasets.MNIST(root='../dataset/mnist',
train=True,
download=True,
transform=transform)
train_loader = DataLoader(train_dataset,
shuffle=True,
batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist',
train=False,
download=True,
transform=transform)
test_loader = DataLoader(test_dataset,
shuffle=False,
batch_size=batch_size)
class Net(torch.nn.Module):
def __init__(self):
"""
搭建连接层
Conv2d(输入通道,输出通道,卷积核是 几乘几的)
MaxPool2d(2) 池化层 除以二;x y 维度上
Linear线性变换
"""
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
self.pooling = torch.nn.MaxPool2d(2)
self.fc = torch.nn.Linear(320, 10)
def forward(self, x):
"""
#Flatten data from (n, 1, 28, 28) to (n, 784)
获取x的第一个参数,返回给batch,即获取batch的大小
先通过 卷积核(conv1) 进行卷积变换 - 进行 池化层(pooling) - 再 正则化(relu)
通过(conv2)卷积核 进行卷积变换 - 进行 池化层(pooling) - 再 正则化(relu)
将做变换好的数据,拉长,变成一个 一维的数据。 - view(batch, -1) 一次处理batch个数据
进行线性变换 - Linear 函数
:param x: 输入数据
:return: 输出数据
"""
batch_size = x.size(0)
x = F.relu(self.pooling(self.conv1(x)))
x = F.relu(self.pooling(self.conv2(x)))
x = x.view(batch_size, -1)
x = self.fc(x)
return x
"""
实例化Net类
判断在GPU还是cpu上跑,这里是在gpu上
将模型放在gpu上(to.(device))
代价函数
优化器,初始化模型参数(权重,偏置),学习率0.01, 为了防止局部最优,在进行迭代时,再加一个函数,这里设置为0.5,和学习率一个等级
"""
model = Net()
device = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
"""
train_loader 传出 batch的索引,即第几次数据, data当前数据
将数据的特征和标签传给 inputs,和 target
将数据传入gpu上
优化器中的梯度设置为零
将数据放入模型中
criterion计算损失值
.backward - 反向传播
优化器函数进行更新权重
将损失值进行累加 传给 running_loss函数
输出第300次及300的倍数次的测试数据 -- 第几次迭代, 当前的第几组数据,即第几个batch,当前损失和
每300次,损失值做一个归结
"""
inputs, target = data
inputs, target = inputs.to(device), target.to(device)
optimizer.zero_grad()
# forward + backward + update
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
"""
torch.no_grad()不用计算梯度
对测试数据进行遍历
将数据的 特征和标签 分别传给 images和labels
数据传到gpu上
带入模型进行预测 得到预测结果 - outputs
这里是,我们取出概率最大的那个数作为输出
取出标签的第一列, 进行累加,即计算总的数据集长度
判断正确的数量,进行累加
输出正确率
"""
for data in test_loader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on test set: %d %%' % (100 * correct / total))
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
"""
构建数据处理函数 - 取出数据 - 进行数据处理(训练,测试)
搭建晓得模块的模型
再搭建整个模型 - 传入小模型,共同构建新的模型
实例化模型 - 选择损失函数,优化器
传入训练集对模型进行训练,传入测试集进行测试
写主函数
"""
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
import torch.nn as nn
"""
设置batch
调用数据转换函数,transform函数
取出训练集,达到训练数据 - train_dataset
将训练集用DataLoader函数进行处理, shuffle数据打乱,batch个数据合成一个数据
测试集同样操作,只是没有打乱数据的操作
"""
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307, ), (0.3081, ))
])
train_dataset = datasets.MNIST(root='../dataset/mnist',
train=True,
download=True,
transform=transform)
train_loader = DataLoader(train_dataset,
shuffle=True,
batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist',
train=False,
download=True,
transform=transform)
test_loader = DataLoader(test_dataset,
shuffle=False,
batch_size=batch_size)
class InceptionA(nn.Module):
def __init__(self, in_channels):
"""
Inception类---继承Module类,
重新写__init__ forward 方法
搭建
卷积层:branch1*1 = Conv2d(输入通达数,输出通道数,卷积核1*1)
卷积层:branch5*5_1 = Conv2d(输入通道数,输出通道数,卷积核1*1)
卷积层:branch5*5_2 = Conv2d(输入通道数,输出通道数,卷积核5*5,步长padding=2)
卷积层:branch3*3_1 = Conv2d(输入通道数,输出通道数,卷积核1*1)
卷积层:branch3*3_2 = Conv2d(输入通道数,输出通道数,卷积核3*3,步长padding=1)
卷积层:branch3*3_3 = Conv2d(输入通道数,输出通道数,卷积核3*3,步长padding=1)
卷积层:branch_pool = Conv2d(输入通道数,输出通道数,卷积核3*3,步长padding=1)
:param in_channels: 输入通道数,即输出数据的通道数(厚度)
"""
super(InceptionA, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)
self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)
self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)
self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)
def forward(self, x):
"""
1、将数据用branch1*1进行处理--branch1*1
2、将数据用branch5*5_1进行处理,再将处理过的数据放进branch5*5_2卷积层进行训练--branch5*5_2
3、将数据用branch3x3_1进行处理,再将处理过的数据放进branch3x3_2卷积层进行训练得到新的数据,再讲这些数据放入branch3x3_3层得到__branch3x3
4、将数据用avg_pool2d进行卷积操作,再将得到的数据放进branch_pool卷积进行训练得到--branch_pool
将得到的四组数据进行整合--outputs
# b,c,w,h c对应的是dim=1,通道数
:param x:输入数据
:return:训练后的通道数
"""
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5_1(x)
branch5x5 = self.branch5x5_2(branch5x5)
branch3x3 = self.branch3x3_1(x)
branch3x3 = self.branch3x3_2(branch3x3)
branch3x3 = self.branch3x3_3(branch3x3)
branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
branch_pool = self.branch_pool(branch_pool)
outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
return torch.cat(outputs, dim=1)
class Net(nn.Module):
def __init__(self):
"""
Net继承Module类
重写__init__ 和 forward 方法
搭建
卷积层:Conv2d(输入通道,输出通道,卷积核大小)--conv1
卷积层:Conv2d(输入通道,输出通道,卷积核大小)--conv2
调用Inception方法--incep1
调用Inception方法--incep2
池化层 MaxPool2d函数--mp
搭建线性层Linear(输入数据维度,输出维度)--fc
"""
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(88, 20, kernel_size=5)
self.incep1 = InceptionA(in_channels=10)
self.incep2 = InceptionA(in_channels=20)
self.mp = nn.MaxPool2d(2)
self.fc = nn.Linear(1408, 10)
def forward(self, x):
"""
取出x的size的第一位,获取batch的大小,这里可以根据模型实例化后,看传入的参数是什么,这里取得是参数的size 的 第一个数据,这里是一个数据有多少数据组成的
x - 卷积层conv1 - 进行池化mp - 正则化relu(调用的F中的relu函数)- x
将得到的x - 放入incep1中得到新的 - x
x - 卷积层conv2 - 进行池化mp - 正则化relu(调用的F中的relu函数)- x
将得到的x - 放入incep2中得到新的 - x
将x用.view函数将二维数据转化成一维数据
记性线性变换
:param x:输入数据
:return:返回结果
"""
in_size = x.size(0)
x = F.relu(self.mp(self.conv1(x)))
x = self.incep1(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.incep2(x)
x = x.view(in_size, -1)
x = self.fc(x)
return x
"""
实例化类 - model
判断是在什么上运行gpu or cpu
将模型放在GPU上
调用损失函数--criterion
悬着SGD优化器,模型参数初始化(权重,偏置,.parameters), 学习率0.01,momentum = 0.5,更好的进行求最小值,减少局部最优
"""
model = Net()
device = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
"""
取出训练数据 - 第几个数据, 输入数据
将数据取出特征和标签 - inputs, target
将数据放入gpu上
优化器的梯度设置为0
将数据的特征放入模型,进行训练
计算损失函数 - loss
反向传播, - .backward
优化器函数进行梯度迭代,更新权重和偏置
损失累加 - running_loss
每300个数据进行输出一次(第几次迭代,第几个数据,损失是多少)
并且损失running_loss置零
"""
inputs, target = data
inputs, target = inputs.to(device), target.to(device)
optimizer.zero_grad()
# forward + backward + update
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
"""
不用计算梯度
遍历测试集
将数据的 特征和标签 传给 - images labels
将数据放在GPU上
将特征放入模型进行训练 - outputs
取出结果的最大值, max
计算标签的长度,即计算测试了多少数量 通过累加 返回给 - total
计算预测正确的函数进行累加 - correct
输出正确率
"""
for data in test_loader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on test set: %d %%' % (100 * correct / total))
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
import torch.nn as nn
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307, ), (0.3081, ))
])
train_dataset = datasets.MNIST(root='../dataset/mnist',
train=True,
download=True,
transform=transform)
train_loader = DataLoader(train_dataset,
shuffle=True,
batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist',
train=False,
download=True,
transform=transform)
test_loader = DataLoader(test_dataset,
shuffle=False,
batch_size=batch_size)
class ResidualBlock(nn.Module):
def __init__(self, channels):
super(ResidualBlock, self).__init__()
self.channels = channels
self.conv1 = nn.Conv2d(channels, channels,
kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(channels, channels,
kernel_size=3, padding=1)
def forward(self, x):
y = F.relu(self.conv1(x))
y = self.conv2(y)
return F.relu(x + y)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
self.conv2 = nn.Conv2d(16, 32, kernel_size=5)
self.mp = nn.MaxPool2d(2)
self.rblock1 = ResidualBlock(16)
self.rblock2 = ResidualBlock(32)
self.fc = nn.Linear(512, 10)
def forward(self, x):
in_size = x.size(0)
x = self.mp(F.relu(self.conv1(x)))
x = self.rblock1(x)
x = self.mp(F.relu(self.conv2(x)))
x = self.rblock2(x)
x = x.view(in_size, -1)
x = self.fc(x)
return x
model = Net()
device = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
inputs, target = data
inputs, target = inputs.to(device), target.to(device)
optimizer.zero_grad()
#forward + bakward + iupdata
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 2000))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on test set: %d %%' % (100 * correct / total))
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
batch_size = 1
seq_len = 3
input_size = 4
hidden_size = 2
"""
单个RNN
即循环神经网络的单个部分
多个部分组成的是RNN
"""
cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)
#(seq, batch, features)
"""
生成标准正态分布的(均值为零,方差为一,的高斯白噪声)的随机数;
.randn生成(3,1,4) -- 张量
生成为全为0.的数,
.zeros生成(1,2) -- 张量
"""
dataset = torch.randn(seq_len, batch_size, input_size)
hidden = torch.zeros(batch_size, hidden_size)
print(dataset)
for idx, input in enumerate(dataset):
"""
idx:第几次遍历
input:取出当前次数的数据,数据维度是(1,4)
cell(输入数据(batch,特征的向量维度),记忆体维度(batch,hidden的维度))
"""
print('=' * 20, idx, '=' * 20)
hidden = cell(input, hidden)
print('outputs size: ', hidden.shape)
print(hidden)
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
batch_size = 1
seq_len = 3
input_size = 4
hidden_size = 2
num_layers = 1
"""
循环神经网络函数RNN
(输入数据(数据的时间维度x的个数,batch,单个数据的维度),记忆体数据(层数(也即第几层的hidden),hidden的维度),层数)
"""
cell = torch.nn.RNN(input_size=input_size, hidden_size=hidden_size,
num_layers=num_layers)
#(seqLen, batchSize, inputSize)
inputs = torch.randn(seq_len, batch_size, input_size)
hidden = torch.zeros(num_layers, batch_size, hidden_size)
"""
输出数据:
out:(seq_len,batch,hidden数据维度)--最上边的那一行,横着的,也就是输出
hidden:(层数,batch,hidden数据维度)
"""
out, hidden = cell(inputs, hidden)
print('Output size: ', out.shape)
print('Output: ', out)
print('Hidden size: ', hidden.shape)
print('Hidden: ', hidden)
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
batch_size = 1
# seq_len = 3
input_size = 4
hidden_size = 4
# num_layers = 1
"""
创建字典
设置输入数据中,每一个x的索引位置构成一个列表
同理。构建一个列表y
构建独热向量(one-hot)
利用for循环,搭建出每一个x对应的向量
-----
将搭建好的数据通过.view方法
构建张量
inputs(seq_len,batch,输入数据)(5,1,4)
label(seq_len,batch)
"""
idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [3, 1, 2, 3, 2]
one_hot_lookup = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
x_one_hot = [one_hot_lookup[x] for x in x_data]
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
labels = torch.LongTensor(y_data).view(-1, 1)
class Model(torch.nn.Module):
def __init__(self, input_size, hidden_size, batch_size):
"""
Model继承Module类
重写__init__;forward;init_hidden方法
init(输入数据维度,记忆体维度,batch)
super超类
调用torch..nn.RNNCell(输入数据的维度,记忆体的维度)函数
:param input_size:(batch,输入数据)
:param hidden_size:(batch,hidden数据)
:param batch_size:(batch)
"""
super(Model, self).__init__()
#self.num_layers = num_layers
self.batch_size = batch_size
self.input_size = input_size
self.hidden_size = hidden_size
self.rnncell = torch.nn.RNNCell(input_size=self.input_size,
hidden_size=self.hidden_size)
def forward(self, input, hidden):
"""
方法,直接使用RNNCell函数,进行训练
:param input: (batch,inputs)
:param hidden: (batch,hidden)
:return: (out(batch,hidden))
"""
hidden = self.rnncell(input, hidden)
return hidden
def init_hidden(self):
"""
使用torch中的zeros函数,生成维度为(batch,hidden),数值为(0.)的张量
:return:
"""
return torch.zeros(self.batch_size, self.hidden_size)
"""
实例化Model类 -- net
使用CrossEntropyLoss函数计算损失 -- criterion
选择Adam优化器,初始化模型参数(W_hh,W_ih,B_ih,B_hh),学习率为0.1
"""
net = Model(input_size, hidden_size, batch_size)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)
for epoch in range(15):
"""
遍历15次
损失值为更新为0
梯度值为0
取出训练集的特征和对应的标签 - 一次取一组,for循环来取
将特征集填入模型,传出hidden-即输出值
通过criterion函数计算损失值进行累加
通过max函数取出,hidden中最大值,返回其索引位置 -- idx
输出当前预测的结果
反向传播
优化器更新参数(权值,偏置,梯度)
每次循环完,输出当前的循环的损失值
"""
loss = 0
optimizer.zero_grad()
hidden = net.init_hidden()
print('Predicted string: ', end='')
for input, label in zip(inputs, labels):
hidden = net(input, hidden)
loss += criterion(hidden, label)
_, idx = hidden.max(dim=1)
print(idx2char[idx.item()], end='')
loss.backward()
optimizer.step()
print(', Epoch [%d/15] loss = %.4f' % (epoch + 1, loss.item()))
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
batch_size = 1
seq_len = 5
input_size = 4
hidden_size = 4
num_layers = 1
idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [3, 1, 2, 3, 2]
"""
inputs(seq_len 5,batch 1,input_size 4)
"""
one_hot_lookup = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
x_one_hot = [one_hot_lookup[x] for x in x_data]
inputs = torch.Tensor(x_one_hot).view(seq_len, batch_size, input_size)
labels = torch.LongTensor(y_data)
class Model(torch.nn.Module):
def __init__(self, input_size, hidden_size, batch_size, num_layers=1):
"""
继承Module类
super超类
重写__init__,forward方法
调用RNN函数(输入数据维度,记忆层数据,层数)
:param input_size:
:param hidden_size:
:param batch_size:
:param num_layers:
"""
super(Model, self).__init__()
self.num_layers = num_layers
self.batch_size = batch_size
self.input_size = input_size
self.hidden_size = hidden_size
self.rnn = torch.nn.RNN(input_size=self.input_size,
hidden_size=self.hidden_size,
num_layers=num_layers)
def forward(self, input):
"""
创建记忆层的维度(hidden:层数,batch,hidden维度)
out:最后一层的输出值(即预测值)--(seq_len,batch,input_size)
_ :最后时刻的hidden的值 -- (num_layers,batch,hidden_size)
:param input: 输入数据
:return:seq_len,hidden_size(每个时间的数据都会有个out,我们将每一个out组合起来,
out中的一个数据和hidden是一样的维度,因为out_1 = g(W_oh * hidden))相当于我们自己定义了out的维度
"""
hidden = torch.zeros(self.num_layers,
self.batch_size,
self.hidden_size)
out, _ = self.rnn(input, hidden)
return out.view(-1, self.hidden_size)
"""
实例化类--net 参数:输入数据,记忆层数据,batch,层数
调用损失函数
选择Adam优化器,模型初始化(W_ih,W_hh,B_ih,B_hh)学习率为0.05
"""
net = Model(input_size, hidden_size, batch_size, num_layers)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)
for epoch in range(15):
"""
优化器函数的梯度设置为0
将数据放入net模型中
计算损失函数
反向传播
优化器更新权值,偏置,梯度等
期初每一个数据的最大值的索引,
一次输出索引值对应的字母
输出 迭代次数和损失函数
"""
# loss = 0
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
_, idx = outputs.max(dim=1)
idx = idx.data.numpy()
print('Predicted: ', ''.join([idx2char[x] for x in idx]), end='')
print(', Epoch [%d/15] loss = %.3f' % (epoch + 1, loss.item()))
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
num_class = 4
batch_size = 1
seq_len = 5
input_size = 4
hidden_size = 8
num_layers = 2
embedding_size = 10
"""
创建字典,创建由特征索引构成的二维向量(1,5),和对应的标签对应字母索引所构成的(5)
将x_data y_data转换为张量 (1,5)(5)
"""
idx2char = ['e', 'h', 'l', 'o']
x_data = [[1, 0, 2, 2, 3]]
y_data = [3, 1, 2, 3, 2]
inputs = torch.LongTensor(x_data)
labels = torch.LongTensor(y_data)
class Model(torch.nn.Module):
def __init__(self):
"""
Model继承Module类
super超类
重写__init__,forward方法
调用Embedding函数,(input_size,embedding_size)--将input_size变成embedding_size(4-10)每一个数据4维变成10维
调用RNN函数(输入维度,记忆层维度,层数)batch_first=true则喂数据时为:input(batch_size,seq_len,hidden_size)
batch_first=False则喂数据时为:input(seq_len,batch_size,hidden_size)
Linear(hidden_size,类别数量)
"""
super(Model, self).__init__()
self.emb = torch.nn.Embedding(input_size, embedding_size)
self.rnn = torch.nn.RNN(input_size=embedding_size,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True)
self.fc = torch.nn.Linear(hidden_size, num_class)
def forward(self, x):
"""
创建记忆体(全是0. 维度(层数,input_size(0) - 即batch_size),hidden_size)
先对输入数据进行Embedding,嵌入层,将input_size -- embedding_size;得到高维数据---(batch_size,seq_len,embedding_size)
将得到的数据进行rnn模型进行训练(x(batch_size,seq_len,embedding_size),hidden(num_layers,batch,hidden_size))
返回out最后一层的输出,和 hidden最后时刻的记忆体的参数
out:(batch,seq_len,embedding)
_ :(num_layer,batch_size, hidden_size)
通过线性函数Linear。维度是num_class
.view()展示的是将(out即x)的每一个值都组合起来,变成(seq_len,num_class)batch_size
:param x: 输入数据input
"""
hidden = torch.zeros(num_layers, x.size(0), hidden_size)
x = self.emb(x)
x, _ = self.rnn(x, hidden)
x = self.fc(x)
return x.view(-1, num_class)
"""
实例化类--net
调用损失函数--criterion
调用Adam优化器,初始化net模型中的参数(权重,偏置),学习率0.05
"""
net = Model()
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)
for epoch in range(15):
"""
优化器的梯度设置为0
将input放入模型,返回out的数据(是矩阵(seq_len,num_class))
计算损失函数
反向传播
优化器迭代,更新参数(权重,偏置,梯度)
通过max返回每一组数据的最大值对应的索引
查找出字典对应索引的字母,输出
输出当前迭代次数和损失值
"""
# loss = 0
optimizer.zero_grad()
outputs = net(inputs)
print(outputs.shape)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
_, idx = outputs.max(dim=1)
idx = idx.data.numpy()
print('Predicted: ', ''.join([idx2char[x] for x in idx]), end='')
print(', Epoch [%d/15] loss = %.3f' % (epoch + 1, loss.item()))
#加油加油加油
#认真对待每一行代码
#努力写好每一行代码
#搞懂每一行代码
import torch
from torch.utils.data import Dataset, DataLoader
from torch.nn.utils.rnn import pack_padded_sequence
import time
import matplotlib.pyplot as plt
import numpy as np
import gzip
import csv
import math
"""
hidden_size=100,batch_size=256,n_layer=2,n_epochs=100,n_chars=128,
记忆体维度100,batch维度为256,层数为2层,迭代次数100次,
"""
HIDDEN_SIZE = 100
BATCH_SIZE = 256
N_LAYER = 2
N_EPOCHS = 100
N_CHARS = 128
USE_GPU = True
class NameDataset(Dataset):
"""
NameDataset类继承Dataset类
重写__init__,__getitem__,__len__方法
定义getCountryDict,idx2country,getCountriesNum函数
实例化后,返回的有:
countries:list,数据中的第二列即所有国家,无排序,无去重
country_dict:dict:18,数据中所有国家,有排序,有去重,{键;键值}
country_list:list:18,数据中所有国家,有排序,有去重
country_num:int:18
len:int,数据中名字的长度,即所有数据的数量
names:list,数据所有名字,有排序
"""
def __init__(self, is_train_set=True):
"""
这个文件是第一列为名字,第二列为国家
:param is_train_set: 用于判断文件类型
使用gzip方法读取文件(解压读取)
再用csv的方法将提取的文件读取,
再用list方法将数据转换成列表 -- rows
name = 取出rows列表中每个元素的第一个值;即文件的第一列 -- 名字
len = 多少个名字
counties = 取出rows列表中每个元素的第二个值,即文件的第二列 -- 国家
set:去重,无序。将contries列表中的国家去重,随机存放 -- 假设返回 - A 列表
将A列表进行排序,从小到大,按首字母再其次俺第二个字母(可以根据ASCII码)-返回列表 -- country_list
country_dict = 调用getCountryDict函数 将列表转换为字典
country_num = 取出country_list的长度,返回国家有多少个
"""
filename = 'names_train.csv.gz' if is_train_set else 'names_test.csv.gz'
with gzip.open(filename, 'rt') as f:
reader = csv.reader(f)
rows = list(reader)
self.names = [row[0] for row in rows]
self.len = len(self.names)
self.countries = [row[1] for row in rows]
self.country_list = list(sorted(set(self.countries)))
self.country_dict = self.getCountryDict()
self.country_num = len(self.country_list)
def __getitem__(self, index):
"""
:param index:
:return: 返回名字的索引,国家从小到大的索引位置,对应字典中的位置
"""
return self.names[index], self.country_dict[self.countries[index]]
def __len__(self):
"""
:return: 求长度
"""
return self.len
def getCountryDict(self):
"""
创建一个空字典 -- country_dict
for循环,取出当前循环次数,和当前循环的名字
存放字典,对应索引,
:return:将列表转换为字典。(键,键值)
"""
country_dict = dict()
for idx, country_name in enumerate(self.country_list, 0):
country_dict[country_name] = idx
return country_dict
def idx2country(self, index):
"""
返回country_list的值
"""
return self.country_list[index]
def getCountriesNum(self):
"""
:return: 国家的数量
"""
return self.country_num
"""
实例化NameDataset类 -- trainset
利用DataLoader函数对数据进行处理,batch_size个数据为一组,shuffle打乱数据 -- trainloader
实例化NameDataset类 -- testset
利用DataLoader函数对数据进行处理,batch_size个数据为一组,shuffle不打乱数据 -- testloader
返回国家的数量(调用NameDataset类)
"""
trainset = NameDataset(is_train_set=True)
trainloader = DataLoader(trainset, batch_size=BATCH_SIZE, shuffle=True)
testset = NameDataset(is_train_set=False)
testloader = DataLoader(testset, batch_size=BATCH_SIZE, shuffle=False)
N_COUNTRY = trainset.getCountriesNum()
"""
^^^^^数据的处理阶段^^^^^
"""
def create_tensor(tensor):
"""
传入张量
判断USE_GPU:
将数据传到cuda上
"""
if USE_GPU:
device = torch.device("cuda:0")
tensor = tensor.to(device)
return tensor
class RNNClassifier(torch.nn.Module):
"""
RNNClassifier继承Module类
重写__init__,_init_hidden,forward,方法。
"""
def __init__(self, input_size, hidden_size, output_size, n_layers=1, bidirectional=True):
"""
super超类
:param input_size:输入数据维度
:param hidden_size:记忆体维度
:param output_size:输出数据维度
:param n_layers:层数
:param bidirectional:判断是双向还是单向传播
Embedding:嵌入层,先对输入数据做一个预处理,从input_size维度到hidden维度
GRU模型,hidden_size:,hidden_size:,n_layers:,
fc:Linear:线性模型:hidden_size * n_directions(输入模型维度),输出模型维度
"""
super(RNNClassifier, self).__init__()
self.hidden_size = hidden_size
self.n_layers = n_layers
self.n_directions = 2 if bidirectional else 1
self.embedding = torch.nn.Embedding(input_size, hidden_size)
self.gru = torch.nn.GRU(hidden_size, hidden_size, n_layers,
bidirectional=bidirectional)
self.fc = torch.nn.Linear(hidden_size * self.n_directions, output_size)
def _init_hidden(self, batch_size):
"""
搭建记忆体的维度(self.n_layers * self.n_directions,batch_size,hidden_size)
返回:记忆体传到模型GPU上
"""
hidden = torch.zeros(self.n_layers * self.n_directions,
batch_size, self.hidden_size)
return create_tensor(hidden)
def forward(self, input, seq_lengths):
"""
数据流程
batch_size = 输入数据的宽度,
hidden的维度调用_init_hidden方法
将数据进行embedding层;
使用pack_padded_sequence函数得到 - gru_input
将处理好的数据传入gru模型函数中返回 -- output,hidden
判断是单向还是双向传播
最后将记忆层进行星星层变换得到输出的结果,并返回
forward:输入数据,时间长度
:param input:输入数据
:param seq_lengths:时间序列
:return:对记忆体的参数进行fc全连接变换,输出,即out
"""
#input shape: B x S --> S x B 转置
input = input.t()
batch_size = input.size(1)
hidden = self._init_hidden(batch_size)
embedding = self.embedding(input)
#pack them up
gru_input = pack_padded_sequence(embedding, seq_lengths)
output, hidden = self.gru(gru_input, hidden)
if self.n_directions == 2:
hidden_cat = torch.cat([hidden[-1], hidden[-2]], dim=1)
else:
hidden_cat = hidden[-1]
fc_output = self.fc(hidden_cat)
return fc_output
def name2list(name):
"""
:param name: 名字
:return: 名字,长度
"""
arr = [ord(c) for c in name]
return arr, len(arr)
def make_tensors(names, countries):
"""
for循环,调用name2list函数,传参数给--sequences_and_lengths
取出名字
取出长度,变成张量
创建全是0.的维度为(len(name_sequences),seq_lengths.max()),并变为长整型 -- 行:名字数,列:最长的ascii名字
遍历,并返回,最后构建seq_tensor[idx,:seq_len]的矩阵, --- zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
排序,依据序列长度降序
"""
sequences_and_lengths = [name2list(name) for name in names]
name_sequences = [s1[0] for s1 in sequences_and_lengths]
seq_lengths = torch.LongTensor([s1[1] for s1 in sequences_and_lengths])
#make rensor of name, BatchSize x SeqLen
seq_tensor = torch.zeros(len(name_sequences), seq_lengths.max()).long()
for idx, (seq, seq_len) in enumerate(zip(name_sequences, seq_lengths), 0):
seq_tensor[idx, :seq_len] = torch.LongTensor(seq)
#sort by length to use pack_padded_sequence
seq_lengths, perm_idx = seq_lengths.sort(dim=0, descending=True)
seq_tensor = seq_tensor[perm_idx]
countries = countries[perm_idx]
return create_tensor(seq_tensor), \
create_tensor(seq_lengths), \
create_tensor(countries)
def time_since(since):
"""
时间计时模块
"""
s = time.time() - since
m = math.floor(s / 60)
s -= m * 60
return '%dm %ds' % (m, s)
def trainModel():
"""
loss初始为0在循环之外;
将训练集传入,取出数据,生成输入数据,长度,标签
放入classifier模型训练
利用criterion函数计算损失值
梯度归零
反向传播
优化器迭代,更新参数(权重,偏置)
损失值累加
输出
:return:所有数据一次的损失
"""
total_loss = 0
for i, (names, countries) in enumerate(trainloader, 1):
inputs, seq_lengths, target = make_tensors(names, countries)
output = classifier(inputs, seq_lengths)
loss = criterion(output, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
if i % 10 == 0:
print(f'[{time_since(start)}] Epoch {epoch}', end='')
print(f'[{i * len(inputs)} / {len(trainset)}]', end='')
print(f'loss = {total_loss / (i * len(inputs))}')
return total_loss
def testModel():
"""
测试集
不用计算梯度
取出数据
将特征放入,计算预测值
求预测数据中的最大值,dim=1--每一行
损失累加
输出
:return:错误率
"""
correct = 0
total = len(testset)
print("evaluating trained model ...")
with torch.no_grad():
for i, (names, countries) in enumerate(testloader, 1):
inputs, seq_lengths, target = make_tensors(names, countries)
output = classifier(inputs, seq_lengths)
pred = output.max(dim=1, keepdim=True)[1]
correct += pred.eq(target.view_as(pred)).sum().item()
percent = '%.2f' % (100 * correct / total)
print(f'Test set: Accuracy {correct} / {total} {percent} %')
return correct / total
if __name__ == '__main__':
"""
模型RNNClassifier
GPU运行
损失函数criterion
优化器Adam:初始化模型参数
记录时间
输出:一共输出多少次
创建一个列表
for循环对N_EPOCHS(1 - n_epochs+1)
跑训练模型
跑测试模型 -- acc
将返回值依次存放在acc_list[]列表中
画图部分
x轴为acc_list的长度,间距为1
y轴为acc_list的数值
"""
classifier = RNNClassifier(N_CHARS, HIDDEN_SIZE, N_COUNTRY, N_LAYER)
if USE_GPU:
device = torch.device("cuda:0")
classifier.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(classifier.parameters(), lr=0.001)
start = time.time()
print("Traning for %d epochs..." % N_EPOCHS)
acc_list = []
for epoch in range(1, N_EPOCHS + 1):
#Train cycle
trainModel()
acc = testModel()
acc_list.append(acc)
epoch = np.arange(1, len(acc_list) + 1, 1)
acc_list = np.array(acc_list)
plt.plot(epoch, acc_list)
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.grid()
plt.show()