参考链接:https://blog.csdn.net/Cowry5/article/details/80367832
1.多分类分类器
将之前实施的logistic分类拓展到one-vs-all分类
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
1.1数据集
数据在ex3data1.mat。5000个训练样本,每个图片大小20×20转化为400维,矩阵X为5000×400。
#加载数据集,数据的格式为matlab格式,使用scipy.io的loadmat
def load_data(path):
data = loadmat(path)
X = data['X']
y = data['y']
return X,y
X,y = load_data('ex3data1.mat')
print(np.unique(y))#查看有积累标签
X.shape,y.shape
#有5000个训练样本,20×20的灰度图像,展开成400的向量
#5000×400的矩阵X
#将逻辑回归实现为完全向量化
#
[ 1 2 3 4 5 6 7 8 9 10]
((5000, 400), (5000, 1))
1.2可视化数据
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()
print('this should be {}'.format(y[pick_one]))
def plot_100_image(X):
'''
随机画100个数字
'''
sample_idx = np.random.choice(np.arange(X.shape[0]),100)#随机选100个样本
sample_images = X[sample_idx,:]#(100,400)
fig,ax_array = plt.subplots(nrows=10,ncols=10,sharey=True,sharex=True,figsize=(8,8))
for row in range(10):
for column in range(10):
ax_array[row,column].matshow(sample_images[10*row+column].reshape((20,20)),
cmap='gray_r')
plt.xticks([])
plt.yticks([])
plt.show()
plot_100_image(X)
1.3 向量化logistic回归
使用one-vs-all逻辑回归模型来构建一个多类分类器。既然有10类,需要训练10个分类logistic回归分类器。为了提高培训的效率使用向量化。实现不使用任何for循环的逻辑回归的向量化版本。可以使用上一个练习中的代码作为起点。
1.3.1 向量化代价函数
正则化:
def sigmoid(z):
return 1/(1+np.exp(-z))
def regularized_cost(theta,X,y,l):
'''
dont't oenalize theta_0
args:
X:feature matrix,(m,n+1);#插入了x0=1
y: traget vector,(m,)
l:lambda constant for regularization
'''
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
1.3.2 正则化向量化梯度
def regularized_gradient(theta,X,y,l):
'''
don't penalize theta_0
args:
l:lambda constant
return:
a vector of gradient
'''
thetaReg = theta[1:]
first= (1/len(X))*X.T@(sigmoid(X @ theta) - y)
#人为插入一组θ,使得对Θ0不惩罚,方便计算
reg = np.concatenate([np.array([0]),(l/len(X))*thetaReg])
return first +reg
1.4 一对多分类器
首先,我们为X添加了一列常数项 1 ,以计算截距项(常数项)。 其次,我们将y从类标签转换为每个分类器的二进制值(要么是类i,要么不是类i)。 最后,我们使用SciPy的较新优化API来最小化每个分类器的代价函数。 如果指定的话,API将采用目标函数,初始参数集,优化方法和jacobian(渐变)函数。 然后将优化程序找到的参数分配给参数数组。
实现向量化代码的一个更具挑战性的部分是正确地写入所有的矩阵,保证维度正确。
https://blog.csdn.net/Cowry5/article/details/80367832
from scipy.optimize import minimize
def one_vs_all(X,y,l,K):
'''
generalized logistic regression
args:
X: feature matrix,(m,n+1)#with incercept x0=1
y: target vector,(m,)
l: lambda constant for regurization
k: numbel of labels
return : trained parameters
'''
all_theta = np.zeros((K,X.shape[1]))
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
1.4.1 一对多预测
一对所有预测函数将选择相应的logistic回归分类器输出的概率最大,且返回类标签(1,2,…,或K)作为输入示例的预测,在代码中预测类别需要+1
def predict_all(X,all_theta):
# compute the class probability
h = sigmoid(X @ all_theta.T)#(5000,10)
#为最大可能的类别创建下标数组
#返回最大值的切片
h_argmax = np.argmax(h, axis=1)
#因为我的数组是0索引,我们需要加一得到真实标签预测
h_argmax = h_argmax+1
return h_argmax #5000个样本的预测值
raw_X,raw_y= load_data('ex3data1.mat')
X = np.insert(raw_X, 0,1,axis=1)
y = raw_y.flatten()
all_theta = one_vs_all(X,y,1,10)
all_theta
ex3.m将使用Θ的学习值。应该知道训练集的准确度94.9%(即对训练集中94.9%的例子进行了正确分类)。
y_pred = predict_all(X,all_theta)
accuracy = np.mean(y_pred == y)
print('accuracy = {0}%'.format(accuracy*100))
accuracy = 94.46%
2神经网络
使用训练好的权重实现一个前馈神经网络
def load_weight(path):
data = loadmat(path)
return data['Theta1'],data['Theta2']
theta1,theta2 =load_weight('ex3weights.mat')
theta1.shape, theta2.shape
((25, 401), (10, 26))
在数据加载函数中,原始数据做了转置,然而,转置的数据与给定的参数不兼容,因为这些参数是由原始数据训练的。 所以为了应用给定的参数,我需要使用原始数据(不转置)
#使用原始数据
X,y = load_data('ex3data1.mat')
y =y.flatten()
X = np.insert(X,0,values=np.ones(X.shape[0]),axis=1)
X.shape,y.shape
((5000, 401), (5000,))
a1 = X
z2 = a1@theta1.T
z2.shape
(5000, 25)
z2 = np.insert(z2,0,1,axis=1)
a2 = sigmoid(z2)
a2.shape
(5000, 26)
z3 = a2@ theta2.T
z3.shape
(5000, 10)
a3 = sigmoid(z3)
a3.shape
(5000, 10)
y_pred = np.argmax(a3,axis=1)+1
accuracy = np.mean(y_pred == y)
print('accuracy = {0}%'.format(accuracy*100))
accuracy = 97.52%