【转】:https://mathpretty.com/10526.html
修改了模型的结构:效果显著
# @TIME : 2019/7/9 下午8:42
# @File : FizzBuzz_new.py
import numpy as np
import torch
import torch.nn as nn
import torch.utils.data as tud
from torch.autograd import Variable
# 准备数据
def binary_encode(i, num_digits):
return np.array([i >> d & 1 for d in range(num_digits)])
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
# training data -> 注意这里没有扯什么反转
NUM_DIGITS = 10 # 十个位数来表达
# 注意后面是923个数据,选择不同的batch,只会影响到最后一波剩下的个数,然后计算准确率,最后每次都会更新一次epoch的准确率
# dataloader 中已经预设了 batch,跑完一波,就计算一下
trX = np.array([binary_encode(i, NUM_DIGITS) for i in range(101, 2**NUM_DIGITS)])
trY = np.array([fizz_buzz_encode(i) for i in range(101, 2**NUM_DIGITS)])
print("trX[:5] = \n",trX[:5])
print('--------------')
print("trY[:5] = \n",trY[:5])
# 准备模型
class FizzBuzzModel(nn.Module):
def __init__(self, in_features, out_classes, hidden_size, n_hidden_layers):
super(FizzBuzzModel, self).__init__()
# 注意有多层的hidden layers
layers = []
for i in range(n_hidden_layers):
layers.append(nn.Linear(hidden_size, hidden_size))
layers.append(nn.BatchNorm1d(hidden_size))
layers.append(nn.ReLU())
self.inputLayer = nn.Linear(in_features, hidden_size)
self.relu = nn.ReLU()
self.layers = nn.Sequential(*layers)
self.outputLayer = nn.Linear(hidden_size, out_classes)
def forward(self, x):
x = self.inputLayer(x)
x = self.relu(x)
x = self.layers(x)
out = self.outputLayer(x)
return out
# 训练模型
# 初始化
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = FizzBuzzModel(10, 4, 150, 3).to(device)
print("model = ", model)
learning_rate = 0.02
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# DataLoader $ 有点迷
FizzBuzzDataset = tud.TensorDataset(torch.from_numpy(trX).float().to(device),
torch.from_numpy(trY).long().to(device))
dataloader = tud.DataLoader(dataset=FizzBuzzDataset, batch_size=300, shuffle=True)
# 训练
model.train()
for epoch in range(1, 300):
for i, (batch_x, batch_y) in enumerate(dataloader):
# print('batch_x= ', batch_x, 'shape = ', batch_x.shape)
# print('batch_y= ', batch_y, 'shape = ', batch_y.shape)
out = model(batch_x)
loss = loss_fn(out, batch_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
correct = 0
total = 0
# print('out.data', out.data, out.data.shape)
_, predicted = torch.max(out.data, 1) # 取每行中最大的概率值
# print('predicted = ', predicted, predicted.shape)
total += batch_y.size(0)
correct += (predicted == batch_y).sum().item()
acc = 100*correct/total
print('Epoch : {:0>4d} | Loss : {:<6.4f} | Train Accuracy : {:<6.2f}%'.format(epoch,loss,acc)) #小数点后面的位数
# 模型测试
def fizz_buzz_decode(i, prediction):
return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]
# 模型预测:需要切换为 eval模式
model.eval()
testX = np.array([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])
predicts = model(torch.from_numpy(testX).float().to(device))
_, res = torch.max(predicts, 1)
predictions = [fizz_buzz_decode(i, prediction) for (i, prediction) in zip(range(1, 101), res)]
print('------------------------------')
print('prediction = \n', predictions )
模型结构:
model = FizzBuzzModel(
(inputLayer): Linear(in_features=10, out_features=150, bias=True)
(relu): ReLU()
(layers): Sequential(
(0): Linear(in_features=150, out_features=150, bias=True)
(1): BatchNorm1d(150, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
(3): Linear(in_features=150, out_features=150, bias=True)
(4): BatchNorm1d(150, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(5): ReLU()
(6): Linear(in_features=150, out_features=150, bias=True)
(7): BatchNorm1d(150, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(8): ReLU()
)
(outputLayer): Linear(in_features=150, out_features=4, bias=True)
)
结果:
Epoch : 0001 | Loss : 1.7445 | Train Accuracy : 30.43 %
Epoch : 0002 | Loss : 1.2746 | Train Accuracy : 30.43 %
Epoch : 0003 | Loss : 1.2672 | Train Accuracy : 39.13 %
。。。
Epoch : 0296 | Loss : 0.7060 | Train Accuracy : 73.91 %
Epoch : 0297 | Loss : 1.5279 | Train Accuracy : 43.48 %
Epoch : 0298 | Loss : 0.6122 | Train Accuracy : 86.96 %
Epoch : 0299 | Loss : 0.0958 | Train Accuracy : 95.65 %
prediction =
['1', '2', 'fizz', '4', 'buzz', 'fizz', '7', '8', 'fizz', 'buzz', '11', 'fizz', '13', '14', 'fizzbuzz', '16', '17', 'fizz', '19', 'buzz', 'fizz', '22', '23', 'fizz', 'buzz', '26', 'fizz', '28', '29', 'fizzbuzz', '31', '32', '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', 'fizz', 'fizz', 'buzz', '71', 'fizz', '73', '74', 'fizzbuzz', '76', '77', 'fizz', '79', 'buzz', 'fizz', '82', '83', 'fizz', 'fizz', '86', 'fizz', '88', '89', 'fizzbuzz', '91', '92', 'fizz', '94', 'buzz', 'fizz', '97', '98', 'fizz', 'buzz']