神经网络实现fizzbuzz小游戏

目录

一、分步骤

1、输入输出

2、模型定义

3、测试

二、总代码

1、训练阶段

2、测试阶段


FizzBuzz是一个简单的小游戏,从1开始往上数数,当遇到3的倍数的时候,说fizz,当遇到5的倍数的时候说buzz,当遇到15的倍数的时候说fizzbuzz,其他情况则正常数数。 写一个简答的小程序决定返回的是正常数值还是fizz、buzz、fizzbuzz。

一、分步骤

1、输入输出

(1)输入:

将输入数据变为10位的2进制编码(二进制编码好训练),一共可以训练1024个数,取[1,101)为测试集,[101,1024)为训练集。

需要的函数即为将输入数据变成10位二进制编码:

import numpy as np
num_digits=10
def binary_encode(i,num_digital):
    return np.array([i >> d & 1 for d in range(num_digital)][::-1])#i每次循环右移d位,并和1相与,最后的编码逆序输出即可

(2)输出:

输出通常为一个数字,即可以把输出定义为:0:输出数据本身,1:输出fizz,2:输出buzz,3:输出fizzbuzz

需要定义一个将每个数字的编码函数,对真实的结果进行编码,以便和模型输出相比较

另还要定义一个解码函数,对模型的预测结果进行解码,将0,1,2,3解码为正确的数字或者英文

import numpy as np
import torch
#先看模型输入和输出,输入是101-1024之间的数,然后对其进行二进制编码训练,所以每个输入数据的维度是10。每个数据真实输出0,1,2,3这几个数(输出编码),输出维度是4,然后对输出进行解码
#模型训练的是数值型的数,所以把正常数值记为0,fizz记为1,buzzj记为2,fizzbuzz记为3,对fizzbuzz进行编码,输入的数据和最后的预测值都为0,1,2,3
def fizzbuzz_encode(i):
    if i%15==0: return 3
    elif i%5==0: return 2
    elif i%3==0: return 1
    else :return 0

#解码,对最后的预测值进行解码,将0,1,2,3解码成正常数值、fizz、buzz、fizzbuzz
def fizzbuzz_decode(i,prediction):
    return [str(i),"fizz","buzz","fizzbuzz"][prediction]

(3)测试集:

输入:输入是[101,1024)的一个tensor,并变为2进制,为923*10的tensor

真实结果:真实结果是输入的923个数据的编码,为0,1,2,3,是4维的,为923*4的tensor。应该定义为torch.LongTensor类型 ,因为编码后的是0,1,2,3的整数,一般tensor的float32类型的数据

中间隐藏层:Hidden=100(923*100)维的数据

trX=torch.Tensor([binary_encode(i,num_digits) for i in range(101,2**num_digits)])
trY=torch.LongTensor([fizzbuzz_encode(i) for i in range(101,2**num_digits)])

2、模型定义

#模型架构
model=torch.nn.Sequential(
        torch.nn.Linear(num_digits,Hidden,bias=False),
        torch.nn.ReLu(),
        torch.nn.Linear(Hidden,4,bias=False)
)
#损失函数,CrossEntropyLoss()本质是拟合/判断两种分布的相似度有多高,返回4个logits,softmax之后,可以得到个四分类的概率分布,有四种类别
loss_fn=torch.nn.CrossEntropyLoss()
#优化函数
optimizer=torch.optim.Adam(model.parameters(),lr=0.05)
#循环迭代10000次,分批次训练,每批128个数据
batch_size=128
for epoch in range(10000):
    for start in range(101,2**num_digits,batch_size)
        end=start+batch_size
        #取出本批次的batchX和batchY
        batchX=trX[start:end]
        batchY=trY[start:end]
        #前向传播
        y_pred=model(y)
        #loss计算
        loss=loss_fn(y_pred,batchY)
        print("Epoch",epoch,loss)
        #梯度清零
        optimizer.zero_grad()
        #反向传播
        loss.backward()
        #参数优化
        optimizer.step()

3、测试

 

#定义输入和真实结果tensor
testX=torch.Tensor([binary_encode(i,num_digits) for i in range(1,101)]
with torch.no_grad():
    #结果预测及解码输出
    y=model(testX)
    prediction=zip(range(1,101),y.max(1)[1].data.tolist())
    print([fizzbuzz_decode(i,x) for i,x in prediction])


二、总代码

1、训练阶段

import numpy as np
import torch
#先看模型输入和输出,输入是101-1024之间的数,然后对其进行二进制编码训练,所以每个输入数据的维度是10。每个数据真实输出0,1,2,3这几个数(输出编码),输出维度是4,然后对输出进行解码
#模型训练的是数值型的数,所以把正常数值记为0,fizz记为1,buzzj记为2,fizzbuzz记为3,对fizzbuzz进行编码,输入的数据和最后的预测值都为0,1,2,3
def fizzbuzz_encode(i):
    if i%15==0: return 3
    elif i%5==0: return 2
    elif i%3==0: return 1
    else :return 0

#解码,对最后的预测值进行解码,将0,1,2,3解码成正常数值、fizz、buzz、fizzbuzz
def fizzbuzz_decode(i,prediction):
    return [str(i),"fizz","buzz","fizzbuzz"][prediction]
#测试编码解码效果
#for i in range(1,12):
     #print(fizzbuzz_decode(i,fizzbuzz_encode(i)))

#定义模型的输入与输出(训练数据),本次模型使用2进制进行编码,一共训练1024个数,则需10位数表
num_digits=10
def binary_encode(i,num_digital):
    return np.array([i >> d & 1 for d in range(num_digital)][::-1])
#定义输入数据,从[101,1024),x是float32输进去没问题,但y只能是0,1,2,3这几个整数,类型改为LongTensor
trX=torch.Tensor([binary_encode(i,num_digits) for i in range(101,2**num_digits)])
trY=torch.LongTensor([fizzbuzz_encode(i) for i in range(101,2**num_digits)])

#输入是923*10的矩阵,输出是923*1的矩阵,矩阵有四个数据表示,代表4维
num_hidden=100
model=torch.nn.Sequential(
    torch.nn.Linear(num_digits,num_hidden,bias=False),
    torch.nn.ReLU (),
    torch.nn.Linear(num_hidden,4)
)
loss_fn=torch.nn.CrossEntropyLoss()#本质是拟合/判断两种分布的相似度有多高,返回4个logits,softmax之后,可以得到个四分类的概率分布,有四种类别
optimizer=torch.optim.Adam(model.parameters(),lr=0.05)
batch_size=128
for epoch in range(10000):
    for start in range(101,len(trX),batch_size):
        end=start+batch_size
        batchX=trX[start:end]
        batchY=trY[start:end]
        #if torch.cuda.is_available():
            #batchX=batchX.cuda()
            #batchY=batchY.cuda()
        y_pred=model(batchX)
        loss=loss_fn(y_pred,batchY)
        print("epoch:",epoch,loss.item())
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

2、测试阶段

testX=torch.Tensor([binary_encode(i,num_digits) for i in range(1,101)])
with torch.no_grad():
    #testX是100*10的矩阵.testY是100*4的矩阵
    testY=model(testX)
    #testY是一个100*4的矩阵,在0,1,2,3的每个维度上都会有一个概率输出,取概率最大的那个数据,并fizzbuzz_decode.testY.max(1)取出第一个维度上最大的那个数,但是包含两个tensor,第一个是最大的那个值,第二个是在那个位置上取到的,所以只要取出第一个tensor即可
    prediction=zip(range(1,101 ),testY.max(1)[1].data.tolist())
    print([fizzbuzz_decode(i,x) for i,x in prediction])

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值