嗯 觉得自己很棒棒哦 总之进步挺大的 哈哈哈哈
0-9的数字识别 属于多分类问题 需要用到softmax分类的知识 具体讲解请参考下面几个博客:
1
2
3
4
首先有两个数据集 训练集和测试集,两个数据集都有txt文件 如0_0.txt表示该txt文件属于第0类 后面的0表示该类别下的一个训练样本 其实每一个txt文件都是一个样本而且里边的32*32维(1024)的数字代表特征,假设每一个类别都含有80个样本(txt文件),那么总共训练集的特征 800*1024
所以需要把每一个txt在文件读取时都存成一个含有1024个特征的列表 在把所有的txt文件存成一个大的矩阵 总共包括800个样本 每一个样本1024个特征
对于每一个样本也把其对应的label存成800*1的矩阵
这里需要说明一下本次处理 把所有的数据都处理成矩阵了 便于后续进行运算,所以需要特别注意维数 以及矩阵的操作 关于numpy 数组 矩阵的相关知识可以参考其他博客
只要足够细心,基础扎实就可以。
数据集在这里: 解压一下放在指定路径就可以
链接:https://pan.baidu.com/s/1NYYwz55eJPOOE48V6Majig 密码:l6i0
接下来直接上代码(python)
# -*- coding: utf-8 -*-
"""
Created on Thu Mar 29 13:59:05 2018
@author: xuanxuan
"""
#手写数字识别 (自己写的) 纯粹练习所用
import numpy as np
import random
#首先导入数据
def getdata(filename0): #filename0主要是一个参数 根据训练集和测试集的路径不一样 传入的参数也不一样
dataarr=[]
labelarr=[]
for i in range(10):
for j in range(50):
L1=[]
L2=[]
filename=filename0+str(i)+'_'+str(j)+'.txt'
file=open(filename)
for row in range(32):
line=file.readline()
linearr=line.strip('\n')
for conlum in range(32):
L1.append(float(linearr[conlum])) #把每一个txt文件都存到L1列表中其中每个元素都是string L里共2014个 也就是一个txt文件共1024个值 对应data矩阵中一行表示一个样本有1024个特征
#append时一定要注意强制类型转换float()或者int()一下 如果后面要进行矩阵的运算的话 最好这样!!
L2.append(i) #把每一个txt文件的index作为该行样本的label
dataarr.append(L1)
labelarr.append(L2)
#print(np.shape(dataarr),np.shape(labelarr)) #这里的datalabel 500*1024,labelarr 500*1都是二维数组
datamat,labelmat=np.mat(dataarr),np.mat(labelarr)
#print(np.shape(datamat),np.shape(labelmat)) #变成了矩阵
return datamat,labelmat
#由于datamat的一行datamat[1]仍然是一个矩阵 1*1024 和w 1024*10相乘后仍为一个1*10的矩阵 需要构建softmax模型 返回概率最大值以及相应的索引作为预测的类别
def softmax(matx): #matx是一个1*10的矩阵
return np.exp(matx)/np.sum(np.exp(matx),axis=1) #返回的是一个1*10的矩阵 ,矩阵中的每一个元素都被softmax函数处理过就是e指数/10个e值数和
#********************测试softmax()函数**************************
#x=np.mat([1,2,3])
#print(type(x))
#y=softmax(x)
#print(y)
#print(type(Y)) #[[ 0.09003057 0.24472847 0.66524096]] 仍然是一个矩阵 只不过矩阵打印出来之后没有matrix显示了
#接下来求一个1*10矩阵中元素最大的位置 返回该索引位置 和对应的概率值
def findmax(matx): #matx是一个1*10的矩阵 只不过这里的matx被softmax处理过了 归一化之后表示概率值
maxvalue=matx[0,0] #将maxvalue 初始化为1*10矩阵的第一个元素
maxposition=0 #认为是矩阵datamat的某一行datamat[randindex] 1*1024和w 1024*10乘完之后得到的1*10矩阵 最大的为该样本与w0相乘的 也就应该判为0类
for i in range(1,10): #跟其余的9个数进行比较
if maxvalue<matx[0,i]:
maxvalue=matx[0,i]
maxposition=i
return maxvalue,maxposition
#*******************测试finmax()函数**************************
#x=np.mat([0.09003057,0.24472847,0.66524096]) #就是上一步得出的softmax的结果 对应概率值 注意上一步的range(10)这里相应改为3才可以运行 因为这里只有3列
#y1,y2=findmax(x) #y1表示 概率最大的值,y2表示该最大值对应的索引
#print(y1,y2)
def accuracy():
pass
def gradent(traindatamat,trainlabelmat,iternum=150): #triandatamat 500*1024的矩阵 trainlabelmat500*1的矩阵
m,n=np.shape(traindatamat)
#print(m,n) #traindatamat 是500*1024的矩阵
w=np.mat(np.ones((n,10))) #w是1024*10的矩阵 因为一共有10个类别 想要创建矩阵一定要np.mat()! 否则np.ones()是一个array数类型!
alpha=0.05
for i in range(iternum):
for j in range(m):
p,pos=findmax(softmax(traindatamat[j]*w)) #表示对该行样本预测为pos类的概率
#print(p,pos,softmax(traindatamat[j]*w))
if trainlabelmat[j,0]==pos:
w[:,pos]=w[:,pos]-alpha*(-(1-p)*traindatamat[j].T) #w[:,pos]是一个1024*1的矩阵 traindatamat[randindex].T也是一个1024*1的矩阵
else:
w[:,pos]=w[:,pos]-alpha*(-(0-p)*traindatamat[j].T)
#print(w)
return w
#对测试数据集测试准确率:
def accuracy(testdatamat,testlabelmat):
num=0
m,n=np.shape(testdatamat)
#print(m,n) #测试数据集的准确率
for i in range(m):
p,pos,=findmax(softmax(testdatamat[i]*w))
if pos==testlabelmat[i,0]:
num+=1
accu=num/m
return accu
if __name__=="__main__":
filename0="E://pyhtonworkspace//py3-pratice//bymyself_practice//python_mechinelearning_homework//04//softmax_multi_datasets//testDigits//"
filename1="E://pyhtonworkspace//py3-pratice//bymyself_practice//python_mechinelearning_homework//04//softmax_multi_datasets//trainingDigits//"
traindatamat,trainlabelmat=getdata(filename0)
testdatamat,testlabelmat=getdata(filename1)
w=gradent(traindatamat,trainlabelmat,200)
accu=accuracy(testdatamat,testlabelmat)
print(w)
print('\n'+"您预测的准确率可以达到{}".format(accu))
以上。
欢迎交流~~~