<jupyter_start><jupyter_text>FizzBuzzFizzBuzz是一个简单的小游戏。游戏规则如下：从1开始往上数数，当遇到3的倍数的时候，说fizz，当遇到5的倍数，说buzz，当遇到15的倍数，就说fizzbuzz，其他情况下则正常数数。首先，我们可以写一个普通的python代码来完成这个小游戏：<jupyter_code>def fizz_buzz_encoder(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_decoder(i, prediction):
    return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]
   
for i in range(1,16):
     print(fizz_buzz_decoder(i, fizz_buzz_encoder(i)))<jupyter_output>1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz<jupyter_text>接下来，我们尝试使用PyTorch构建一个简单的神经网络模型来玩这个小游戏。 1.准备训练数据<jupyter_code>import numpy as np
import torch

NUM_DIGITS = 10

# 用二进制numpy数组表示输入数字
def binary_encode(i, num_digits):
    return np.array([i >> d & 1 for d in range(num_digits)])

trX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
trY = torch.LongTensor([fizz_buzz_encoder(i) for i in range(101, 2 ** NUM_DIGITS)]) # 由于我们是4分类问题，所以Y需要为整型数据<jupyter_output><empty_output><jupyter_text>2.用PyTorch定义模型<jupyter_code># 隐藏层的维度设置为100
NUM_HIDDEN = 100

model = torch.nn.Sequential(
    torch.nn.Linear(NUM_DIGITS, NUM_HIDDEN),
    torch.nn.ReLU(),
    torch.nn.Linear(NUM_HIDDEN, 4)
)

# 使用cuda加速
if torch.cuda.is_available():
    model = model.cuda()<jupyter_output><empty_output><jupyter_text>3.定义损失函数和优化函数<jupyter_code># 由于是分类问题，我们选择交叉熵函数
loss_fn = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.05)<jupyter_output><empty_output><jupyter_text>4.开始训练<jupyter_code>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]
        # 将数据放到cuda上
        if torch.cuda.is_available():
            batchX = batchX.cuda()
            batchY = batchY.cuda()
        y_pred = model(batchX)
        loss = loss_fn(y_pred, batchY)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    # 打印loss
    print('Epoch:', epoch, 'Loss:', loss.item())<jupyter_output><empty_output><jupyter_text>5.准备测试数据<jupyter_code># 我们用训练好的模型尝试在1到100这些数字上玩FizzBuzz游戏
testX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])

if torch.cuda.is_available():
    testX = testX.cuda()<jupyter_output><empty_output><jupyter_text>6.测试<jupyter_code># 由于测试时不需要保留梯度，故把测试时的梯度清空
with torch.no_grad():
    testY = model(testX)
predictions = zip(range(1, 101), list(testY.max(1)[1].data.tolist()))
print([fizz_buzz_decoder(i, x) for (i, x) in predictions])

testY = testY.cpu()
print("accuracy:", np.sum(testY.max(1)[1].numpy() == np.array([fizz_buzz_encoder(i) for i in range(1,101)])), "%")<jupyter_output>['1', 'buzz', 'fizz', '4', 'buzz', 'fizz', '7', '8', 'fizz', 'buzz', '11', 'fizz', '13', '14', 'fizzbuzz', '16', '17', 'fizz', 'fizz', 'buzz', 'fizz', '22', '23', 'fizz', 'buzz', '26', 'fizz', '28', '29', 'fizzbuzz', '31', 'buzz', 'fizz', '34', 'buzz', 'fizz', '37', '38', 'fizz', 'buzz', '41', 'fizz', '43', '44', 'fizzbuzz', '46', '47', 'fizz', '49', 'buzz', 'fizz', '52', '53', 'fizz', 'buzz', '56', 'fizz', '58', '59', 'fizzbuzz', '61', '62', 'fizz', '64', 'buzz', 'fizz', '67', '68', 'fizz', 'buzz', '71', 'fizz', '73', '74', 'fizzbuzz', '76', '77', 'fizz', '79', 'buzz', 'fizz', '82', 'fizz', 'fizz', 'buzz', '86', 'fizz', '88', '89', 'fizzbuzz', '91', '92', 'fizz', '94', 'buzz', 'fizz', '97', '98', 'fizz', 'buzz']
accuracy: 96 %
{'fraction_non_alphanumeric': 0.19608407716671467, 'fraction_numerical': 0.05269219694788367, 'mean_word_length': 5.159574468085107, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '99017', 'license': 'Apache-2.0', 'n_tokens_mistral': 1788, 'n_tokens_neox': 1741, 'n_words': 289, 'path': 'code/FizzBuzz.ipynb', 'repo_name': 'aimi-cn/official-pytorch-tutorial', 'size': '3473'}