python_多元分类_手写字母识别
参考:原文:https://blog.csdn.net/Cowry5/article/details/80367832
1.使用逻辑回归梯度下降方法分析(方便理解,算法没调试好,准确率不高)
代码
from scipy.io import loadmat import numpy as np import matplotlib.pyplot as plt def load_data(path):#导入数据 data=loadmat(path) x=data['X'] y=data['y'] return x,y '''def plot_an_image(X): pick_one=np.random.choice(np.arange(X.shape[0]),100) image=X[pick_one,:] fig, ax=plt.subplots(nrows=10,ncols=10,sharey=True,sharex=True,figsize=(8,8)) for row in range(10): for colum in range(10): ax[row,colum].matshow(image[10*row+colum].reshape((20,20)),cmap='gray_r') plt.xticks([]) plt.yticks([]) plt.show()''' def plot_an_image(X): """ 随机打印一个数字 """ pick_one = np.random.randint(0, 5000) image = X[pick_one, :] fig, ax = plt.subplots(figsize=(1, 1)) ax.matshow(image.reshape((20, 20)), cmap='gray_r') plt.xticks([]) # 去除刻度,美观 plt.yticks([]) plt.show() return pick_one def sigmoid(z): return 1 / (1 + np.exp(-z)) def predict(X,all_theta): X=X.T h=sigmoid(all_theta@X) return h def tiduxiajiang_sigmoid(x,y): alpha=0.0001 maxcycle=50 weights=np.ones(X.shape[1]) weights=np.mat(weights) weights=weights.T x=np.mat(x)#转成矩阵 y=np.mat(y) y=y.T x2=x.T#矩阵转逆 for i in range(maxcycle): h = sigmoid(x* weights) error=y-h weights=weights+alpha*x2*error #print(sum(error)) if(abs(sum(error))<=10): break return weights.T X,y=load_data('ex3data1.mat') X=np.insert(X,0,1,axis=1) all_theta=np.zeros((10,X.shape[1])) for i in range(1,11):#遍历1到10个分类 y_i = np.array([1 if label == i else 0 for label in y])#归类,是就是1不然就归0 all_theta[i-1:]=tiduxiajiang_sigmoid(X,y_i)#梯度下降求theta for j in range(10): pick_one= np.random.randint(0, 5000)#随机生成一个整数在0到5000之间 image = X[pick_one, :] data=predict(image,all_theta) data=list(data) max=0 for i in range(1,len(data)):#将预测值转数字 if(data[max]<data[i]): max=i print(y[pick_one, :],end=" ")#输出原本值 print(max+1)#输出预测值
输出
[2] 2
[1] 8
[4] 4
[8] 8
[9] 8
[7] 7
[5] 8
[1] 8
[4] 4
[1] 8
2.根据上面原文进行一点点修改,准确率较高(主要是minimize的应用)
代码
from scipy.io import loadmat import numpy as np import matplotlib.pyplot as plt from scipy.optimize import minimize def load_data(path):#导入数据 data=loadmat(path) x=data['X'] y=data['y'] return x,y def plot_an_image(X): """ 随机打印一个数字 """ pick_one = np.random.randint(0, 5000) '''image = X[pick_one, :] fig, ax = plt.subplots(figsize=(1, 1)) ax.matshow(image.reshape((20, 20)), cmap='gray_r') plt.xticks([]) # 去除刻度,美观 plt.yticks([]) plt.show()''' return pick_one def sigmoid(z): return 1 / (1 + np.exp(-z)) def predict(X,all_theta):#预测函数 X=X.T h=sigmoid(all_theta@X) return h def regularized_cost(theta, X, y, l): thetaReg = theta[1:] first = (-y*np.log(sigmoid(X@theta))) + (y-1)*np.log(1-sigmoid(X@theta)) reg = (thetaReg@thetaReg)*l / (2*len(X)) return np.mean(first) + reg def regularized_gradient(theta, X, y, l): thetaReg = theta[1:] first = (1 / len(X)) * X.T @ (sigmoid(X @ theta) - y) # 这里人为插入一维0,使得对theta_0不惩罚,方便计算 reg = np.concatenate([np.array([0]), (l / len(X)) * thetaReg]) return first + reg def one_vs_all(X, y, l, K): all_theta = np.zeros((K, X.shape[1])) # (10, 401) for i in range(1, K+1): theta = np.zeros(X.shape[1]) y_i = np.array([1 if label == i else 0 for label in y]) ret = minimize(fun=regularized_cost, x0=theta, args=(X, y_i, l), method='TNC', jac=regularized_gradient, options={'disp': True}) all_theta[i-1,:] = ret.x return all_theta raw_X, raw_y = load_data('ex3data1.mat') x=raw_X X = np.insert(raw_X, 0, 1, axis=1) # (5000, 401) y2=raw_y y = raw_y.flatten() # 这里消除了一个维度,方便后面的计算 or .reshape(-1) (5000,) all_theta = one_vs_all(X, y, 1, 10) for j in range(10): pick_one=np.random.randint(0, 5000) image = X[pick_one, :] data=predict(image,all_theta) data=list(data) max=0 for i in range(1,len(data)):#将预测值转数字 if(data[max]<data[i]): max=i print(y2[pick_one, :],end=" ") print(max+1)
输出
[1] 1
[8] 8
[2] 8
[10] 10
[5] 5
[9] 9
[5] 5
[10] 10
[2] 2
[9] 9