# 随机梯度下降import time
import numpy as np
# 显示进度条from tqdm import tqdm
# mnist数据集将数据集做一个首尾拼接,28*28=784defloaddata(filename):"""
加载mnist数据集
:param filename: 要加载的数据集路径
:return: list形式的数据集及标签
"""print('start to read data')# 存放数据
dataArr =[]
labelArr =[]# 打开文件
fr =open(filename,'r')# 将文件进行按行读取for line in tqdm(fr.readlines()):# 将读取后的每一行按切割符切割,并返回字段列表
curline = line.strip().split(',')# 存放标记# Mnsit有0-9是个标记,由于是二分类任务,所以将>=5的作为1,<5为-1ifint(curline[0])>=5:
labelArr.append(1)else:
labelArr.append(-1)# 归一化-遍历每一行除了第一个元素外的所有元素,并归一化# 列表推导式
dataArr.append([int(num)/255for num in curline[1:]])# 返回data和labelreturn dataArr, labelArr
defperceptron(dataArr, labelArr,iter=50):"""
感知机训练过程
:param dataArr: 训练集的数据
:param labelArr: 训练集的标签
:param iter: 迭代次数
:return: 训练好的w和b
"""print('strat to train')# 将数据转换成矩阵形式,矩阵可以并行计算,方便运算
dataMat = np.mat(dataArr)# 将标签转换成矩阵后,在进行转置# 转置是因为运算中需要单独取label中的某一个元素
labelMat = np.mat(labelArr).T
# 获取数据矩阵的shape,m*n
m, n = np.shape(dataMat)# 创建初始权重w,初始值全为0。
w = np.zeros((1, n))# 初始化偏置b为0
b =0# 初始化步长η,即学习率,控制梯度下降速率
η =0.001# 迭代计算for k inrange(iter):# 采用随机梯度下降-计算一个样本,就针对该样本做一个梯度下降for i inrange(m):# 获取当前样本的向量及标签
xi = dataMat[i]
yi = labelMat[i]# 判断是否为误分类样本,如果为误分类样本,则进行梯度更新# 误分类样本特征:-1 * yi * (w * xi.T + b) >= 0if-1* yi *(w * xi.T + b)>=0:
w = w + η * yi * xi
b = b + η * yi
# 打印训练进度print('Round %d : %d training'%(k,iter))return w, b
defmodel_test(dataArr, labelArr, w, b):"""
测试准确率
:param dataArr:测试数据集
:param labelArr: 测试标签
:param w: 权重
:param b: 偏置
:return: 测试集的准确率
"""print('start to test')
dataMat = np.mat(dataArr)
labelMat = np.mat(labelArr).T
m, n = np.shape(dataMat)
errornum =0for i inrange(m):
xi = dataMat[i]
yi = labelMat[i]
result =-yi *(w * xi.T + b)# 如果result >= 0,说明被错误分类if result >=0:
errornum +=1# 正确率 = 1 - 错误率
accurRate =1-(errornum / m)return accurRate
if __name__ =='__main__':# 获取当前时间
start = time.time()# 加载数据集
trainData, trainLabel = loaddata('data/mnist_train.csv')
testData, testLabel = loaddata('data/mnist_test.csv')# 获取训练后的权重
w, b = perceptron(trainData, trainLabel)# 进行测试获得准确率
accurRate = model_test(testData, testLabel, w, b)# 获取当前时间,作为结束时间
end = time.time()# 显示正确率print('accuracy rate is:', accurRate)# 显示用时时长print('time span:', end - start)
start to read data
100%|██████████|60000/60000[00:11<00:00,5247.08it/s]
start to read data
100%|██████████|10000/10000[00:01<00:00,5326.08it/s]
strat to train
Round 0:50 training
Round 1:50 training
Round 2:50 training
Round 3:50 training
Round 4:50 training
Round 5:50 training
Round 6:50 training
Round 7:50 training
Round 8:50 training
Round 9:50 training
Round 10:50 training
Round 11:50 training
Round 12:50 training
Round 13:50 training
Round 14:50 training
Round 15:50 training
Round 16:50 training
Round 17:50 training
Round 18:50 training
Round 19:50 training
Round 20:50 training
Round 21:50 training
Round 22:50 training
Round 23:50 training
Round 24:50 training
Round 25:50 training
Round 26:50 training
Round 27:50 training
Round 28:50 training
Round 29:50 training
Round 30:50 training
Round 31:50 training
Round 32:50 training
Round 33:50 training
Round 34:50 training
Round 35:50 training
Round 36:50 training
Round 37:50 training
Round 38:50 training
Round 39:50 training
Round 40:50 training
Round 41:50 training
Round 42:50 training
Round 43:50 training
Round 44:50 training
Round 45:50 training
Round 46:50 training
Round 47:50 training
Round 48:50 training
Round 49:50 training
start to test
accuracy rate is:0.8141
time span:111.59057807922363