当前位置: 首页 > 工具软件 > Buzz > 使用案例 >

简单的搭建一个神经网络(fizz_buzz)

禹昆
2023-12-01

 

首先我们采用一个简单的小游戏进行神经网络的初步学习

游戏的简单介绍——从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表示索引中的内内容

这样,我们就通过定义一个小游戏,然后通过神经网络进行学习,并让神经网络完成这个游戏

 类似资料: