首先我们采用一个简单的小游戏进行神经网络的初步学习
游戏的简单介绍——从1开始数数,如果是3的倍数输出fizz,是5的倍数输出buzz,是15的倍数输出fizzbuzz
下面这串代码我们将文件名命名为fizz_buzz,存放在chapter2文件夹下,在接下来的神经网络学习过程中,我们需要用到
# 首先我们对所数的数(i)据进行编码
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):
return [str(i), "fizz", "buzz", "fizzBuzz"][prediction]
# 我们创建一个游戏的工具,调用这个工具游戏就开始进行
def helper(i):# 传入i,输出最终的结果
print(fizz_buzz_decode(i, fizz_buzz_encode(i)))
if __name__ == '__main__':
for i in range(1, 16):
helper(i)
到此游戏不通过神经网络的办法我们已经实现了
接下来我们在神经网络的学习中调用上面的方法,就可以得到训练数据和训练数据的结果
# 通过神经网络来实现fizzbuzz,这里采用了两层的神经网络
import numpy as np
import torch as t
from chapter2.fizz_buzz import fizz_buzz_encode
from chapter2.fizz_buzz import fizz_buzz_decode
NUM_DIGITS = 10 # 二进制的位数最多表示到1024,也就是说,我们对所属的数进行编码时,数组的长度是10
isCuda = t.cuda.is_available()# 查看系统是不是包含GPU
# 我们可以把输入转换为二进制,这样的话会更加有利于网络,因为这样输入数据的维度进行了变化
def binary_encode(i, num_digits):
# 二进制的内容存储到了一个数组中
return np.array([i >> d & 1 for d in range(num_digits)][::-1])
# 这里面的内容是把for逆序使用了,i的表示用for进行了迭代
# 将数的数转换为二进制,并转换为tensor的数组
trainX = t.Tensor([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
# 这里我们调用了前面所说的方法,调用fizz_buzz_encode函数的到输出的结果
trainY = t.LongTensor([fizz_buzz_encode(i) for i in range(101, 2 ** NUM_DIGITS)])
NUM_HIDDEN = 100 # 设置隐藏层的维度
model = t.nn.Sequential( # 创建一个模型来实现,这样在这个模型中,我们只需要叠加就可以
t.nn.Linear(NUM_DIGITS, NUM_HIDDEN), # 我们先从10维准换为100维度,这是第一层
t.nn.ReLU(), # 第一层的激活函数采用ReLU
t.nn.Linear(NUM_HIDDEN, 4) # 4 logits, after softmax, we probability distribution
)
# 如果有gpu就使用gpu
if isCuda:
model = model.cuda()
loss_fn = t.nn.CrossEntropyLoss() # 这是一个用于分类问题的损失函数
optimizer = t.optim.SGD(model.parameters(), lr=0.05) # 创建一个优化器,使用优化器可以对梯度的变化进行优化
BATCH_SIZE = 128 # 设置打包的个数
# 开始进行训练,训练10000次,每次是101-1024个数据
for epoch in range(10000):
for start in range(0, len(trainX), BATCH_SIZE): # 我们按照batch进行拿取数据
# 进行批处理数据的准备,这里不会产生越界的问题,最后一批的时候有多少取多少
end = start + BATCH_SIZE
batchX = trainX[start:end]
batchY = trainY[start:end]
if isCuda: # 有gpu则用gpu进行计算
batchX = batchX.cuda()
batchY = batchY.cuda()
# forward
y_prad = model(batchX)
loss = loss_fn(y_prad, batchY)
# 打印损失率
# print("Epoch", epoch, loss.item())
# backward
optimizer.zero_grad() # 进行导数的清零,防止叠加
loss.backward()
optimizer.step() # 进行一步操作,这里进行了权重的变化
# 进行测试,这里我们采用前面训练时没有进行使用过的数据
testX = t.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 100)])
if isCuda:
testX = testX.cuda()
# 这里表示,下面的进行模型的时候我们不用求导,从而节省资源
with t.no_grad():
testY = model(testX) # 注意这里的类型是(100,4),每一行表示一个测试,测试的结果对应这个元素的可能性
# max会返回两个数组,第[0]个表示最大的值,第[1]个表示最大的值的下标
predictions = zip(range(1, 101), testY.max(1)[1].cpu().data.tolist()) # 打包乘乘一个元组((a,b),(c,d)...)
print([fizz_buzz_decode(i, x) for i, x in predictions]) # i表示索引,x表示索引中的内内容
这样,我们就通过定义一个小游戏,然后通过神经网络进行学习,并让神经网络完成这个游戏