1.固定结构
-
#搭建前向网络 class Net(torch.nn.Module): def __init__(self,input_features,hidden_nums,output_features): super(Net,self).__init__() …… …网络结构:Linear、Conv… …… def forward(self,x): 调用上边的网络结构 #return 返回值 return x
-
#调用神经网络,传入网络层的参数 net = Net(10,100,4)
-
#定义优化器,传入:net网络的所有参数,学习率 optimizer = torch.optim.SGD(net.parameters(),lr = 0.05)
-
#定义损失函数 loss_func = torch.nn.CrossEntropyLoss() #此例使用交叉熵
-
#开始迭代 for iterate in range(1,10001): #预测值 predict = net(……) #计算损失 loss = loss_func(predict,…GroundTruth…) #优化三部曲:清0—>反向传播—>更新 optimizer.zero_grad() loss.backward() optimizer.step()
2. 是否使用with torch.no_grad()——两者计算的结果实际上是没有区别的
-
使用with torch.no_grad():,强制之后的内容不进行计算图构建
-
不使用with torch.no_grad():有grad_fn=属性,表示,计算的结果在一计算图当中,可以进行梯度反传等操作。
-
主要是在测试集中,使用with torch.no_grad(),因为此时不再进行反向传播更新参数
执行结果:
测试
testX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])
with torch.no_grad():
测试结果存放在testY中
testY = net(testX)
print(testY.shape)
print("1-*-*-*-*-*-1-*-*-*-*-*-1")
predictions = zip(range(1, 101), list(testY.max(1)[1].data.tolist()))
print([fizz_buzz_decode(i, x) for (i, x) in predictions])
print("预测正确个数:",sum( testY.max(1)[1].data.tolist() == np.array([fizz_buzz_encode(i) for i in range(1,101)]) ) )
3.完整程序:搭建神经网络实现FizzBuzz游戏
import torch
import numpy as np
import torch.nn.functional as F
def fizz_buzz_encode(i):
if (i % 15 == 0):
return 3
elif (i % 5 == 0):
return 2
elif (i % 3 == 0):
return 1
else:
return 0
def fizz_buzz_decode(i, prediction):
#当前数字i由str(i)
# 转换成字符串,
# prediction代表的数,来控制输出字符串中的哪一个
return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]
#控制二进制数的长度为10
NUM_DIGITS = 10
#十进制数据转换成2进制数据,故意搞混乱让软件自己去学出规律
def binary_encode(i,num_digits):
#移位取出i的二进制位
return np.array([i>>d & 1 for d in range(num_digits)])
#训练集数据
trX = torch.Tensor([binary_encode(i,NUM_DIGITS) for i in range(101,2**NUM_DIGITS)])
#对应正确数据集
trY = torch.LongTensor([fizz_buzz_encode(i) for i in range(101,2**NUM_DIGITS)])
#搭建前向网络
class Net(torch.nn.Module):
def __init__(self,input_features,hidden_nums,output_features):
super(Net,self).__init__()
self.hiddenNet1 = torch.nn.Linear(input_features,hidden_nums)
self.prediction = torch.nn.Linear(hidden_nums,output_features)
def forward(self,x):
x = F.relu(self.hiddenNet1(x))
x = self.prediction(x)
return x
#调用神经网络
net = Net(10,100,4)
#定义优化器,传入:net网络的所有参数,学习率
optimizer = torch.optim.SGD(net.parameters(),lr = 0.05)
#定义损失函数
loss_func = torch.nn.CrossEntropyLoss() #使用均方误差
#开始迭代
BATCH_SIZE=128
for iterate in range(1,10001):
for start in range(0, len(trX), BATCH_SIZE):
end = start + BATCH_SIZE
# 取出trX的128行
batch_X = trX[start:end]
# 取出trY的128行
batch_Y = trY[start:end]
#预测值
predict = net(batch_X)
#计算损失
loss = loss_func(predict,batch_Y)
#优化三部曲:清0—>反向传播—>更新
optimizer.zero_grad()
loss.backward()
optimizer.step()
loss = loss_func(net(trX), trY).item()
if iterate % 100 == 0 :
print("Train Epoch:{}:{}".format(
iterate,
loss
))
#测试
testX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])
with torch.no_grad():
# 测试结果存放在testY中
testY = net(testX)
print(testY.shape)
print("1-*-*-*-*-*-1-*-*-*-*-*-1")
# 把1维数组[1~100]和testY的每行4个元素中最大的那个的坐标通过zip压缩在一起
predictions = zip(range(1, 101), list(testY.max(1)[1].data.tolist()))
# 输出预测结果
print([fizz_buzz_decode(i, x) for (i, x) in predictions])
#通过.numpy()、.tolist()或.data.tolist(),转换成数组进行比较
#通过sum()或者np.sum(),对比较后的数组进行求和,看看有几个是计算对的
print("预测正确个数:",sum( testY.max(1)[1].data.tolist() == np.array([fizz_buzz_encode(i) for i in range(1,101)]) ) )