逻辑回归的多分类问题——识别手写数字
- 了解.mat文件
- 读取数据划分集合
- 测试图片
- 损失函数
- 认识Scipy.iptimize.minimze优化函数
- 梯度向量
- 优化函数
了解.mat文件
.mat文件是属于matlab的文件,具体有什么特点和属性还不知道,但对于本题中我们需要去读取,要用到python中的Scipy库下的loadmat模块吧应该,去读取.mat文件。
读取数据划分集合
import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio
data = sio.loadmat('data/ex3data1.mat')
raw_X = data['X']
raw_y = data['y']
print(data,type(data))
print(raw_X.shape,raw_y.shape)
>>> ...
>>> <type dict>
>>> (5000, 400) (5000, 1)
用到的方法:
作用 | 代码 |
读取mat文件 | data = sio.loadmat(‘data/ex3data1.mat’) |
用到了scipy.io模块下的.loadmat方法,专门用于读取matlab类型的文件,返回的类型是字典dict,可以从jupyter中看到raw_X的类型是array数组类型,并且猜测这是图片的二进制数组格式,本质上就是一张张照片。
可以从raw_X的形状中得知,(5000,400)中的400原本应该是二维的20x20像素的图片,为便于保存拉伸为1x400,所以5000就是5k张照片。
测试图片
def plot_image(X):
rdm = np.random.choice(5000,100)
images = X[rdm,:]
print(images.shape)
fig,ax = plt.subplots(ncols=10,nrows=10,figsize=(8,8),sharex=True,sharey=True)
for i in range(10):
for j in range(10):
ax[i,j].imshow(images[10 * i + j].reshape(20,20).T,cmap='gray_r')
plt.xticks([])
plt.yticks([])
plt.show()
用到的方法:
作用 | 代码 |
获取区间内的随机整数 | rdm = np.random.randint(5000) |
获取区间内的多个随机整数 | rdm = np.random.choice(5000) |
显示图片 | ax.imshow(image.reshape(20,20).T,cmap = ‘gray_r’) |
图片的信息都存储在raw_X的每一行中,每行的数组都是一张图片,随机选取一行,获取图片的信息后还需要对其形状进行改变,因为此时获取的是(1,400)需要转换为(20,20)的,所以在ax.imshow()方法中改变了数组的形状,显示图片的方法是ax.imshow(),第一个参数是图片的数组信息,第二个参数是颜色和底色。
损失函数
def costFunction(theta,X,y,lamda):
A = sigmoid(X @ theta)
first = y * np.log(A)
second = (1 - y) * np.log(1 - A)
reg = theta[1:] @ theta[1:] * (lamda / (2*len(X)))
return -np.sum(first + second) / len(X) + reg
本题的损失函数,相对于非线性分类问题中的损失函数差不多,公式用的一样。
认识Scipy.iptimize.minimze优化函数
因为本题比较复杂,所以我们不用自己编写梯度下降函数而是调包使用现成的方法。
这个方法用于优化函数(这里要优化的函数就是costFunction损失函数)
梯度向量
我们不需要自己重新编写梯度下降方法,但是我们要提供给改方法梯度向量
这是梯度下降函数的公式,而梯度向量就是后面那一坨。
def gradient_reg(theta,X,y,lamda):
reg = theta[1:] * (lamda / len(X))
reg = np.insert(reg,0,values=0,axis=0)
first = (X.T @ (sigmoid(X @ theta) -y )) / len(X)
return first + reg
优化函数
from scipy.optimize import minimize
def one_vs_all(X,y,lamda,K):
n = X.shape[1]
theta_all = np.zeros((K,n))
for i in range(1,K+1):
theta_i = np.zeros(n,)
res = minimize(fun=costFunction,
x0 = theta_i,
args=(X,y==i,lamda),
method='TNC',
jac = gradient_reg)
print(res)
theta_all[i-1,:] = res.x
return theta_all
思考原理:我们已经知道了每张图片都是以(401,1)的形状存在于X集合中,其中400个包含图片信息的参数我们都当做了特征,一共400个特征值,1个常数项,所以一会的theta形状也要是(K,401),本题一共需要10个分类器,我们把每个分类器的参数theta都整合到一个theta_all当中。
类似这样:
关于预测部分:
比如有一张图片,它的shape是(401,)比作p1,让theta_all和p1相乘会得到一个长度为10的一维数组。
res = theta_all @ p1
print(res)
>>>array([-16.14447 , -9.78841354, -8.40606098, -16.03911719,
-4.68367905, -14.52251444, -9.24265692, -12.74947102,
-9.37451931, 6.40369668])
这10个数的值就是代表该图片中的数字分别对应0~9的概率,数值越大,则预测越有把握。比如上述代码的值就是9,真实结果也是9。