https://www.bilibili.com/video/BV1mt411p7kG?p=1
https://github.com/boxes757/Machine-learning-exercises/blob/master/机器学习2——逻辑回归练习(分类)
numpy(计算,处理多维数组)、matplotlib.pyplot(绘图框架)、scipy.io(读取.mat文件)、scipy.optimize.minimize(一个或多个变量的函数的最小化)
sigmoid函数 g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z}} g(z)=1+e−z1
对于 h θ ( x ) = g ( θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n ) h_{\theta}(x)=g(\theta_{0}+\theta_{1}x_{1}+\theta_{2}x_{2}+...+\theta_{n}x_{n}) hθ(x)=g(θ0+θ1x1+θ2x2+...+θnxn)来说,我们计算出的 h θ ( x ) h_{\theta}(x) hθ(x)都在(0,1)这个区间内。 在二分类中,我们将 h θ ( x ) h_{\theta}(x) hθ(x)输出的结果理解为对于特征集x来说,y=1的概率。比如 h θ ( x ) = 0.7 h_{\theta}(x)=0.7 hθ(x)=0.7,我们理解为 y = 1 y=1 y=1的概率为0.7。 在多分类中,对于第 i i i 分类器来说,都有一组 [ θ 0 ( i ) , θ 1 ( i ) , . . . , θ n ( i ) ] [\theta_{0}^{(i)},\theta_{1}^{(i)},...,\theta_{n}^{(i)}] [θ0(i),θ1(i),...,θn(i)],我们通过这组值计算出相应的 h θ ( i ) ( x ) h_{\theta}^{(i)}(x) hθ(i)(x)。对于一个样本来说,比较其在各分类器中的 h θ ( i ) ( x ) h_{\theta}^{(i)}(x) hθ(i)(x)值,选取最大的一个,则代表它属于这个分类的概率值最大。
损失函数(带正则项) 损失函数与之前类似,化简后的损失函数为:
梯度下降函数(带正则项) ( θ = θ − ∂ J ( θ ) ∂ θ j \theta = \theta - \frac{\partial J(\theta)}{\partial \theta_{j}} θ=θ−∂θj∂J(θ),注意 j = 0 j = 0 j=0 时与之前的梯度下降函数一致)
读取数据我们用到了scipy.io这个包,我们调用其里面的loadmat来读取.mat文件
import scipy.io as sio data = sio.loadmat('03-neural network/ex3data1.mat')该方法的具体文档可以参考以下链接: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html (官方英文文档) https://blog.csdn.net/cazenove/article/details/107820322(用例) https://www.cnblogs.com/onenoteone/p/12441668.html(用例) 注:
theta为一维向量,在之前例子中为(n,1)二维向量,但用minimize方法时,x0(初始预测值)需为一维向量!!
之前例子中我们使用迭代方法手动进行梯度下降,此处我们只需要计算梯度向量返回给minimize方法中的jac参数即可,我们也不需要手动进行梯度下降时设置的 α \alpha α 值。
带正则化项的梯度向量如下所示:
一维数组与矩阵的乘法 左乘作为行向量运算,右乘作为列向量进行运算,结果得到一维数组 如(2,) ∗ * ∗ (2,4) = (4,) (3,5) ∗ * ∗ (5,) = (3,)
np.zeros 生成由n个0元素组成的一维数组:np.zeros(5)或np.zeros(5,) 生成(2,3)的由0组成的二维数组:np.zeros((2,3)) 注意两层括号
def CostFunction(theta,X,y,lamda): ##theta为一维向量!! R=sigmoid(X@theta) ##theta一维向量,作矩阵乘法时。左乘作为行向量运算,右乘作为列向量进行运算,计算结果也是一维数组 A=y * np.log(R) ##X为(5000,401)矩阵,theta为(401,)一维向量,R是(5000,)一维向量 B=(1-y) * np.log(1-R) ##reg = np.sum(np.power(theta[1:],2)) * (lamda/ (2 * len(X))) reg = theta[1:] @ theta[1:] * (lamda/ (2 * len(X))) ##两种写法结果一致 return -np.sum(A+B)/len(X)+reg def gradient_reg(theta,X,y,lamda): ##带正则化项的梯度向量 A = sigmoid(X @ theta) R = theta[1:] * (lamda / len(X)) R = np.insert(R, 0, values=0, axis=0) grad1 = (X.T @ (A-y)) / len(X) return grad1+R X = np.insert(raw_X,0,values=1,axis=1) print(X.shape) y = raw_y.flatten() ##损失函数中涉及到y与R的运算,R为(5000,)的一维向量,需要将y也转化为一维向量 print(y.shape) from scipy.optimize import minimize def one_vs_all(X,y,lamda,K): ##K是分类器值 n = X.shape[1] ##获取X的第二个维度的值,此处即列数401 theta_all = np.zeros((K,n)) ##此处为(10,401)矩阵 for i in range(1,K+1): ##此处K=10,i取1,2,3,...,10 theta_i = np.zeros(n,) ##以0作为初始值,分别为各分类器运行优化函数 res = minimize(CostFunction,x0=theta_i,args=(X,y == i,lamda),method='TNC',jac=gradient_reg) ##args是将额外参数传入目标函数(该处为损失函数),y==i是将该分类器值代入 ##jac也可以是一个可调用的,返回目标的梯度的函数。在这种情况下,它必须接受与目标函数(该处为损失函数)相同的参数。 theta_all[i-1,:] = res.x ##将结果保存到theta_all的相应位置,注意i为分类器的标号,存储时需要-1 return theta_alltheta_final及准确值(acc):