Pytorch2—python函数体定义、zip、for用法——FizzBuzz游戏实验

1.python基本语法

1.1.函数体定义与调用
  •   def  函数名(参数列表):
      	  函数体
    
  • 先定义,后调用
    在这里插入图片描述
#先定义
def sum(i,j):
    return i+j

#后调用
result=sum(1.2,3)
print("输出结果:%f"%result)
1.2.zip用法
1.2.1.zip()
  • zip(),执行各数组之间的元素打包,而且元素个数与最短的列表一致
  • zip函数返回一个zip类型对象,所以输出时,需要转换为list类型
    在这里插入图片描述
import numpy as np

a = [1, 2, 3]
b = [4, 5, 6]
c = [14, 15, 16, 17, 18]

a_b_zip = zip(a, b)   a,b数组实现打包,而且元素个数与最短的列表一致
print("type of a_b_zip is %s" % type(a_b_zip))   输出zip函数的返回对象类型
a_b_zip = list(a_b_zip)   因为zip函数返回一个zip类型对象,所以需要转换为list类型
print(a_b_zip)
print("-------1-----------------------------------")
a_c_zip = zip(a, c)  a,c数组实现打包,而且元素个数与最短的列表一致
a_c_zip = list(a_c_zip)
print(a_c_zip)
1.2.2.zip(*zipped)
  • 参数为list数组时,是压缩数据,相当于zip()函数
    在这里插入图片描述
import numpy as np

nums = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']]
iterator = zip(*nums)   参数为list数组时,是压缩数据,相当于zip()函数
print("type of iterator is %s" % type(iterator))   输出zip(*zipped)函数返回对象的类型
iterator = list(iterator)   因为zip(*zipped)函数返回一个zip类型对象,所以需要转换为list类型
print(iterator)
1.3.for循环
  • 1.3.1. for 局部变量var in range(start,end,stride):
    从start开始,以stride为步长,直到end-1结束
    eg.输出0~20之间,以5为步长的数
    在这里插入图片描述
for i in range(0,21,5):
    print(i)

或者
在这里插入图片描述

print([i for i in range(0,21,5)])
2.FizzBuzz小实验

FizzBuzz是一个简单的小游戏。游戏规则如下:从1开始往上数数,

  •   当遇到3的倍数的时候,说fizz,
    
  •   当遇到5的倍数,说buzz,
    
  •   当遇到15的倍数,就说fizzbuzz,
    

其他情况下则正常数数。

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

2.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):
    当前数字i由str(i)转换成字符串,
    prediction代表的数,来控制输出字符串中的哪一个
    return [str(i),"fizz","buzz","fizzbuzz"][prediction]

选取1,2,5,12,15进行测试
在这里插入图片描述

print(fizz_buzz_decode(1 , fizz_buzz_encode(1)))
print(fizz_buzz_decode(2 , fizz_buzz_encode(2)))
print(fizz_buzz_decode(5 , fizz_buzz_encode(5)))
print(fizz_buzz_decode(12, fizz_buzz_encode(12)))
print(fizz_buzz_decode(15, fizz_buzz_encode(15)))
2.2.我们首先定义模型的输入与输出

trX训练集数据是:101~1024-1 共 923个数字

import numpy as np
import torch

	控制二进制数的长度为10
NUM_DIGITS = 10

	十进制数据转换成2进制数据,故意搞混乱让软件自己去学出规律
def binary_encode(i,num_digits):
   	移位取出i的二进制位
    return np.array([i>>d & 1  for d in range(num_digits)])

	101~1024-1   923个数字是训练集
trX = torch.Tensor([binary_encode(i,NUM_DIGITS) for i in range(101,2**NUM_DIGITS)])
print("trX.shape:",trX.shape,"trX:",trX)
print("len(trX):",len(trX))

	利用fizz_buzz_encode() 获取真正对的结果
	注意是LongTensor, 因为Tensor默认数据类型为float,
	而fizz_buzz_encode(i)返回数据类型为整型数据,所以用LongTensor
trY = torch.LongTensor([fizz_buzz_encode(i) for i in range(101,2**NUM_DIGITS)])
print("trY.shape:",trY.shape,"trY:",trY)

在这里插入图片描述

2.3.用PyTorch定义模型结构
  • 一个线性层
  • 一个ReLu层
  • 再一个线性层
定义模型
输入层:每个输入结果是10维

隐藏层100个节点
NUM_HIDDEN = 100
输出层:每个输出结果是:4维
NUM_OUT    = 4

model的输入是  (非负正整数x)×10 的tensor
model的输出是  (非负正整数x)×4 的tensor
model=torch.nn.Sequential(
    torch.nn.Linear(NUM_DIGITS,NUM_HIDDEN),
    torch.nn.ReLU(),
    torch.nn.Linear(NUM_HIDDEN,NUM_OUT)

)
2.4.定义一个损失函数,和一个优化算法

由于FizzBuzz游戏本质上是一个分类问题,我们选用Cross Entropyy Loss函数。
优化函数我们选用(SGD)Stochastic Gradient Descent。

定义损失函数
loss_fn = torch.nn.CrossEntropyLoss()
参数列表:模型参数、学习率
optimizer = torch.optim.SGD(model.parameters(),lr = 0.05)
2.5.模型的训练代码

对101~1024-1,这923个数字进行训练
每个batch大小是128

设置批处理size
BATCH_SIZE=128
for epoch in range(10000):
    for start in range(0,len(trX),BATCH_SIZE):
        end     = start + BATCH_SIZE
        取出trX的128行
        batch_X = trX[start:end]
        取出trY的128行
        batch_Y = trY[start:end]
        
        进行预测  128×4
        y_pred  = model(batch_X)
         
        计算损失
        loss    = loss_fn(y_pred,batch_Y)
        
        优化器梯度清0
        optimizer.zero_grad()
        反向传播
        loss.backward()
        参数更新
        optimizer.step()
        
    loss=loss_fn(model(trX),trY).item()
    输出本次迭代的损失
    print("epoch:",epoch,"Loss:",loss)

在这里插入图片描述

2.5.以1~100这100个数字作为测试集测试模型训练效果
  • testY的大小是100×4,是因为,每个输入结果,在输出端都是fizz、buzz、fizzbuzz或者当前数字,这4种情况的可能性概率。
下边这句算法:把testY的100个输出结果,每个结果都选取概率最大的那个,并组成一个list
  •   testY.max(1)[1].data.tolist()
    
testX = torch.Tensor([binary_encode(i, NUM_DIGITS) for i in range(1, 101)])

with torch.no_grad():
	测试结果存放在testY中
    testY = model(testX)
    print(testY.shape)
    print("1-*-*-*-*-*-1-*-*-*-*-*-1")1维数组[1~100]和testY的每行4个元素中最大的那个的坐标通过zip压缩在一起

predictions = zip(range(1, 101), list(testY.max(1)[1].data.tolist()))
输出预测结果
print([fizz_buzz_decode(i, x) for (i, x) in predictions])
2.6.统计100的输入中,有多少个是预测正确的,并输出结果分布图
  • 通过.numpy()、.tolist()或.data.tolist(),转换成数组进行比较
  • 通过sum()或者np.sum(),对比较后的数组进行求和,看看有几个是计算对的
    计算结果:如图所示94个正确,6个错误。
    在这里插入图片描述
#通过.numpy()、.tolist()或.data.tolist(),转换成数组进行比较
#通过sum()或者np.sum(),对比较后的数组进行求和,看看有几个是计算对的
#print( np.sum(  testY.max(1)[1].numpy() == np.array([fizz_buzz_encode(i) for i in range(1,101)])  ) )
#print( np.sum(  testY.max(1)[1].tolist() == np.array([fizz_buzz_encode(i) for i in range(1,101)])  ) )
print("预测正确个数:",sum(  testY.max(1)[1].data.tolist() == np.array([fizz_buzz_encode(i) for i in range(1,101)])  ) )


#输出比较的结果
pred_list=zip( range(1, 101), (testY.max(1)[1].numpy() == np.array([fizz_buzz_encode(i) for i in range(1,101)])).tolist()    )
list(pred_list)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值