4 复习神经网络——FizzBuzz游戏

博客介绍了构建游戏标签的方法,包括定义模型输入输出,用PyTorch定义模型,选用交叉熵损失函数。分别用SGD和Adam优化算法实现模型,并对两种实现方式进行准确率测试,FizzBuzz游戏本质是分类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 构建这个游戏标签的一些方法

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):
    return(fizz_buzz_decode(i, fizz_buzz_encode(i)))
    
for i in range(1, 16):
    print(helper(i), end = ' ')

2 定义模型的输入与输出

import numpy as np
import torch

NUM_DIGITS = 10 # 将数字转换成10位二进制表示

def binary_encode(i, num_digits):
    # 原理:将i的二进制形式的第d位与1做与操作,并将结果依次放入数组中
    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)]) # 训练数据 923*10
trY = torch.LongTensor([fizz_buzz_encode(i) for i in range(101, 2 ** NUM_DIGITS)])      # 标签值 923

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) 
    # 返回四个logits,softmax只有我们获得一个概率分布
)
if torch.cuda.is_available():
    model = model.cuda()
  • 定义一个损失函数和一个优化算法
  • 优化算法是用来不多优化(降低)损失函数,使得模型在该任务上取得尽可能低的损失值
  • FizzBuzz游戏本质上是一个分类问题,选用交叉熵损失函数
  • 优化函数我们选用SGD

4 用SGD实现

loss_fn = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.05)

BATCH_SIZE = 256
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]
        
        if torch.cuda.is_available():
            batchX = batchX.cuda()
            batchY = batchY.cuda()
        
        # forward pass
        y_pred = model(batchX)
        # loss
        loss = loss_fn(y_pred, batchY)
        
        if epoch % 1000 == 0:
            print('Epoch', epoch, loss.item())
            
        optimizer.zero_grad()
        # backward
        loss.backward()
        
        # update
        optimizer.step()
        
    

4.1 测试一下准确率


testX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])

if torch.cuda.is_available():
    testX = testX.cuda()
    
with torch.no_grad():
    testY = model(testX) # 100 * 4
    
predictions = zip(range(1, 101), testY.max(1)[1].cpu().data.tolist()) # 第二个参数是每一样的最大值的索引,并生成列表
predicted = [fizz_buzz_decode(i, x) for i, x in predictions]

right = 0
lens = len(predicted)
for i in range(1, 101):
    if predicted[i-1] == fizz_buzz_decode(i, fizz_buzz_encode(i)):
        right += 1
print(right / lens)

5 用Adam实现

loss_fn = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr = 0.005)

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]
        
        if torch.cuda.is_available():
            batchX = batchX.cuda()
            batchY = batchY.cuda()
        
        # forward pass
        y_pred = model(batchX)
        # loss
        loss = loss_fn(y_pred, batchY)
        
        if epoch % 1000 == 0:
            print('Epoch', epoch, loss.item())
            
        optimizer.zero_grad()
        # backward
        loss.backward()
        
        # update
        optimizer.step()

5.1 测试一下准确率

testX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])
if torch.cuda.is_available():
    testX = testX.cuda()
    
with torch.no_grad():
    testY = model(testX) # 100 * 4

predictions = zip(range(1, 101), testY.max(1)[1].cpu().data.tolist()) # 第二个参数是每一样的最大值的索引,并生成列表
predicted = [fizz_buzz_decode(i, x) for i, x in predictions]

right = 0
lens = len(predicted)
for i in range(1, 101):
    if predicted[i-1] == fizz_buzz_decode(i, fizz_buzz_encode(i)):
        right += 1
print(right / lens)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值