02-简单的两层神经网络FizzBuzz小游戏

FizzBuzz是一个简单的小游戏。游戏规则如下︰从1开始往上数数,当遇到3的倍数的时候,说fizz,当遇到5的倍数,说buzz,当遇到15的倍数,就说fizzbuzz,其他情况下则正常数数。

我们可以写一个简单的小程序来决定要返回正常数值还是fizz, buzz或者fizzbuzz。 

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):
    print(fizz_buzz_decode(i,fizz_buzz_encode(i)))
    
for i in range(1,10):
    helper(i)

#输出结果
1
2
fizz
4
buzz
fizz
7
8
fizz

 但现在我们想机器自己学会玩这个游戏,所以定义一个神经网络。

我们首先定义模型的输入与输出(训练数据):
 

然后我们用PyTorch定义模型:

  • 为了让我们的模型学会FizzBuzz这个游戏,我们需要定义一个损失函数,和一个优化算法。
  • 这个优化算法会不断优化(降低)损失函数,使得模型的在该任务上取得尽可能低的损失值。
  • 损失值低往往表示我们的模型表现好,损失值高表示我们的模型表现差。
  • 由于FizzBuzz游戏本质上是一个分类问题,我们选用Cross Entropyy Loss函数。
  • 优化函数我们选用Stochastic Gradient Descent。

以下是模型的训练代码:

import numpy as np
import torch

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):
    print(fizz_buzz_decode(i, fizz_buzz_encode(i)))

#准备数据
NUM_DIGITS=10
def binary_encode(i,num_digits):#将数字转成二进制
    return np.array([i>>d & 1 for d in range(num_digits)][::-1])


trX=torch.Tensor([binary_encode(i,NUM_DIGITS) for i in range(101,2**NUM_DIGITS)])#输入数据是一堆二进制串
trY=torch.Tensor([fizz_buzz_encode(i) for i in range(101,2**NUM_DIGITS)])#输出数据是对应的结果 0 1 2 3

#然后用PyTorch定义模型
NUM_HIDDEN=100
model=torch.nn.Sequential(
    torch.nn.Linear(NUM_DIGITS,NUM_HIDDEN),
    torch.nn.ReLU(),
    torch.nn.Linear(NUM_HIDDEN,4)
)


#该问题相当于四分类问题,常用的损失函数如下CrossEntropyLoss
loss_fn=torch.nn.CrossEntropyLoss()#交叉熵损失函数
optimizer=torch.optim.SGD(model.parameters(),lr=0.05)

BATCH_SIZE = 128  # 一批数据
for epoch in range(10000):
    for start in range(0, len(trX), BATCH_SIZE):
        end = start + BATCH_SIZE
        batchX = trX[start:end]
        batchY = trY[start:end]

        y_pred = model(batchX)
        loss = loss_fn(y_pred, batchY)
        print("Epoch", epoch, loss.item(), sep='\t')

        optimizer.zero_grad()
        loss.backward()  # 后向传递
        optimizer.step()  # 梯度下降


#最后我们用训练好的模型尝试在1-100这些数字上玩FizzBuzz游戏
testX=torch.Tensor([binary_encode(i,NUM_DIGITS) for i in range(1,101)])
with torch.no_grad():#注意:在测试时候必须no_grad
    testY=model(testX)
predictions=zip(range(1,101),list(testY.max(1)[1]))#因为拿到的是一行中是四个数据的可能性,所以拿出最大值
print([fizz_buzz_decode(i,x)for i,x in predictions])

你可能感兴趣的:(人工智能)