本人跑的时候正确率0.89
库
- numpy
- PIL(如果须要对理论图片进行预测)
后果
- minst的四个文件解压之后和这四个py文件放在同级文件夹
- 运行完结后的权重W和偏移b也在同级文件夹下,csv文件只用来看,用的是bin文件
softmax.py
和训练、测试无关的所有函数
#!/usr/bin/pythonimport numpy as npnp.random.seed(0)# 定义softmax函数def SoftMax(z): if np.ndim(z) == 2: axisn = 1 else: axisn = 0 s = np.exp(z) / np.sum(np.exp(z), axis=axisn, keepdims=True) return s# b = np.array([1,2,4, 5,5,6]).reshape(2,3)# print(SoftMax(b))# 编码标签def OneCode(y): r = len(y) c = len(np.unique(y)) one_hot = np.zeros((r,c)) one_hot[np.arange(len(y)), y.astype(int).T] = 1 return one_hot# 定义 y_ 的计算函数def CalcY_(x, w, b): # w * X.T + b 前面 +b 是一个播送运算, y_ = np.dot(w, x.T) + b return y_.T# 定义损失函数 - 穿插熵def cross_entropy(y, y_): loss = -(1/len(y))*np.sum(y * np.log(y_)) return loss# 定义训练函数def train(tr_x, tr_y, N): ''' ''' # 模型 # y = w1 * x1 + w2 * x2 + b W = np.random.rand(10,784) b = np.random.rand(10,1) losss = [] losi = 0 y = OneCode(tr_y) # 把 1 2 3 4 转换成向量 0001 0010 0100 1000 for i in range(N): # 计算loss x = tr_x y_ = SoftMax(CalcY_(x, W, b)) loss = cross_entropy(y, y_) losss.append(loss) # 计算梯度 grad_w = (1/len(x)) * np.dot((y_ - y).T, x) grad_b = (1/len(x)) * np.sum((y_ - y)) # 更新参数 # 学习率 × 梯度 W = W - 0.5 * grad_w b = b - 0.5 * grad_b delta = abs(losi - loss) print(i , loss ,delta) # 损失值低于0.01 或者 其变动值低于0.0001 if(loss < 0.01 or delta < 0.0001): break losi = loss return W,b# 定义测试函数def check(te_x, te_y, W, b): # te_x,te_y = Iread('te') # te_x = te_x / 255 # te_y = te_y # print(W) # print(b) y_ = SoftMax(CalcY_(te_x, W, b)) l = np.argmax(y_, axis=1).reshape(10000,1) right = np.sum(l == te_y.astype())/10000 print('right rate:', right) return right
Idata.py
文件读取函数
#!/usr/bin/pythonimport numpy as npfilename_train_data ='./train-images-idx3-ubyte'filename_train_label='./train-labels-idx1-ubyte'filename_test_data ='./t10k-images-idx3-ubyte'filename_test_label ='./t10k-labels-idx1-ubyte'def Iread_train_data(): fp = open(filename_train_data, 'rb') fl = open(filename_train_label, 'rb') fp.read(4*4) fl.read(2*4) nstrs=np.zeros((60000, 28*28)) l =np.zeros((60000, 1)) for i in range( 60000): fstr = fp.read(28*28) lstr = fl.read(1) l[i] = int.from_bytes(lstr,byteorder='big',signed=False) nstrs[i,:] = np.frombuffer(fstr, dtype=np.uint8) return nstrs,ldef Iread_test_data(): fp = open(filename_test_data, 'rb') fl = open(filename_test_label, 'rb') fp.read(4*4) fl.read(2*4) nstrs=np.zeros((10000, 28*28)) l =np.zeros((10000, 1)) for i in range( 10000): fstr = fp.read(28*28) lstr = fl.read(1) l[i] = int.from_bytes(lstr,byteorder='big',signed=False) nstrs[i,:] = np.frombuffer(fstr, dtype=np.uint8) return nstrs,ldef Iread(option): if(option == 'tr'): d,l = Iread_train_data() return d,l else if(option == 'te'): d,l = Iread_test_data() return d,l else: print('op err')
minst.py
实现训练和测试的脚本
#!/usr/bin/pythonimport numpy as npfrom Idata import Ireadfrom softmax import train,check# 读数据tr_x,tr_y = Iread('tr')te_x,te_y = Iread('te')# 训练集和测试集正规到 0-1 区间tr_x = tr_x / 255te_x = te_x / 255# print(tr_x.shape, tr_y.shape)# print(te_x.shape, te_y.shape)# 训练W,b = train(tr_x, tr_y, 1000)# 而后保留参数W.tofile('W.bin')b.tofile('b.bin')np.savetxt('w.csv', W, fmt='%f', delimiter=',')np.savetxt('b.csv', b, fmt='%f', delimiter=',')# 读取参数W = np.fromfile('W.bin').reshape(10, 784)b = np.fromfile('b.bin').reshape(10, 1)# 测试r = check(te_x, te_y, W, b)
predict.py
用来对一个理论的手写数字图像识别的脚本
#!/usr/bin/pythonimport numpy as npfrom softmax import SoftMax,CalcY_,cross_entropy,OneCodefrom PIL import Image# 图像文件必须是 28 × 28 的 0~255 灰度图像fname = '4.bmp'img = np.array(Image.open(fname))te_x = img.reshape(1, 28*28)te_x = te_x / 255print(te_x)W = np.fromfile('W.bin').reshape(10, 784)b = np.fromfile('b.bin').reshape(10, 1)y_ = SoftMax(CalcY_(te_x, W, b))y_ = np.argmax(y_, axis=1)print('pred:', y_)