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)