本文不涉及细节理论,只做必要性的介绍,侧重代码实现。
只有二分类是完全不够用的,因此需要其他的算法来解决多分类问题。
多分类分为OvO(One vs One)和OvR(One vs Rest).
这里主要讨论OvR分类器.
例如识别数字0-9有10种情况。
多分类问题模型是从二分类延申出来的。类比二分类即可学习。
从单样本开始
对 于 一 组 样 本 { x , y = j } j ∈ [ 1 , k ] 来 说 。 对 于 x 的 预 测 结 果 可 能 有 多 个 , 如 何 确 定 最 终 的 结 果 呢 ? 判 断 概 率 P ( y = j ∣ θ , x ) , 那 个 概 率 更 大 , 就 预 测 那 个 值 用 h θ ( x ) 表 示 就 是 : 预 测 结 果 h θ ( x ) = { P ( y = 1 ∣ θ , x ) P ( y = 2 ∣ θ , x ) . . . P ( y = k ∣ θ , x ) 从 中 选 择 合 适 的 那 个 概 率 如 何 确 定 概 率 分 布 呢 一 个 x 和 θ 只 能 确 定 一 个 值 , 因 此 x 不 变 的 情 况 下 , 改 变 θ 可 以 获 得 不 同 的 概 率 值 即 我 们 对 每 种 预 测 结 果 都 拟 合 一 个 θ , 判 断 在 那 种 θ 下 的 拟 合 程 度 最 高 即 可 , 判 断 y = j 的 θ 记 为 θ ( j ) P ( y = l ∣ θ , x ) = e θ ( l ) x ∑ j = 1 k e θ ( j ) x 即 : h θ ( x ) = { P ( y = 1 ∣ θ , x ) P ( y = 2 ∣ θ , x ) . . . P ( y = k ∣ θ , x ) = 1 ∑ j = 1 k e θ ( j ) x [ e θ ( 1 ) x e θ ( 2 ) x . . . e θ ( k ) x ] \begin{aligned} & 对于一组样本\{x,y=j\}j\in[1,k]来说。\\ & 对于x的预测结果可能有多个,如何确定最终的结果呢?\\ & 判断概率P(y=j|\theta,x),那个概率更大,就预测那个值\\ & 用h_\theta(x)表示就是:\\ & 预测结果h_\theta(x)= \left\{\begin{matrix} P(y=1|\theta,x)\\ P(y=2|\theta,x)\\ ...\\ P(y=k|\theta,x) \end{matrix}\right.从中选择合适的那个概率\\ & 如何确定概率分布呢\\ & 一个x和\theta只能确定一个值,因此x不变的情况下,改变\theta可以获得不同的概率值\\ & 即我们对每种预测结果都拟合一个\theta,判断在那种\theta下的拟合程度最高即可,判断y=j的\theta记为\theta^{(j)}\\ & P(y=l|\theta,x)=\frac{e^{\theta^{(l)}x}}{\sum_{j=1}^k e^{\theta^{(j)}x}}\\ & 即:\\ & h_\theta(x)= \left\{\begin{matrix} P(y=1|\theta,x)\\ P(y=2|\theta,x)\\ ...\\ P(y=k|\theta,x) \end{matrix}\right.=\frac{1}{\sum_{j=1}^k e^{\theta^{(j)}x}} \begin{bmatrix} e^{\theta^{(1)}x}\\ e^{\theta^{(2)}x}\\ ...\\ e^{\theta^{(k)}x} \end{bmatrix} \end{aligned} 对于一组样本{x,y=j}j∈[1,k]来说。对于x的预测结果可能有多个,如何确定最终的结果呢?判断概率P(y=j∣θ,x),那个概率更大,就预测那个值用hθ(x)表示就是:预测结果hθ(x)=⎩⎪⎪⎨⎪⎪⎧P(y=1∣θ,x)P(y=2∣θ,x)...P(y=k∣θ,x)从中选择合适的那个概率如何确定概率分布呢一个x和θ只能确定一个值,因此x不变的情况下,改变θ可以获得不同的概率值即我们对每种预测结果都拟合一个θ,判断在那种θ下的拟合程度最高即可,判断y=j的θ记为θ(j)P(y=l∣θ,x)=∑j=1keθ(j)xeθ(l)x即:hθ(x)=⎩⎪⎪⎨⎪⎪⎧P(y=1∣θ,x)P(y=2∣θ,x)...P(y=k∣θ,x)=∑j=1keθ(j)x1⎣⎢⎢⎢⎡eθ(1)xeθ(2)x...eθ(k)x⎦⎥⎥⎥⎤
对于多样本,我们只需要对每个样本都进行h(x)即可。
对 于 多 样 本 { ( x ( 1 ) , y ( 1 ) ) , . . . , ( x ( m ) , y ( m ) ) } h θ ( x ( i ) ) = { P ( y ( i ) = 1 ∣ θ , x ( i ) ) P ( y ( i ) = 2 ∣ θ , x ( i ) ) . . . P ( y ( i ) = k ∣ θ , x ( i ) ) = [ e θ ( 1 ) x ( i ) ∑ j = 1 k e θ ( j ) x ( i ) e θ ( 2 ) x ( i ) ∑ j = 1 k e θ ( j ) x ( i ) . . . e θ ( k ) x ( i ) ∑ j = 1 k e θ ( j ) x ( i ) ] = 1 ∑ j = 1 k e θ ( j ) x ( i ) [ e θ ( 1 ) x ( i ) e θ ( 2 ) x ( i ) . . . e θ ( k ) x ( i ) ] 对于多样本\{(x^{(1)},y^{(1)}),...,(x^{(m)},y^{(m)})\}\\ h_\theta(x^{(i)})= \left\{\begin{matrix} P(y^{(i)}=1|\theta,x^{(i)})\\ P(y^{(i)}=2|\theta,x^{(i)})\\ ...\\ P(y^{(i)}=k|\theta,x^{(i)}) \end{matrix}\right.= \begin{bmatrix} \frac{e^{\theta^{(1)}x^{(i)}}}{\sum_{j=1}^k e^{\theta^{(j)}x^{(i)}}}\\ \frac{e^{\theta^{(2)}x^{(i)}}}{\sum_{j=1}^k e^{\theta^{(j)}x^{(i)}}}\\ ...\\ \frac{e^{\theta^{(k)}x^{(i)}}}{\sum_{j=1}^k e^{\theta^{(j)}x^{(i)}}} \end{bmatrix}=\frac{1}{\sum_{j=1}^k e^{\theta^{(j)}x^{(i)}}} \begin{bmatrix} e^{\theta^{(1)}x^{(i)}}\\ e^{\theta^{(2)}x^{(i)}}\\ ...\\ e^{\theta^{(k)}x^{(i)}} \end{bmatrix} 对于多样本{(x(1),y(1)),...,(x(m),y(m))}hθ(x(i))=⎩⎪⎪⎨⎪⎪⎧P(y(i)=1∣θ,x(i))P(y(i)=2∣θ,x(i))...P(y(i)=k∣θ,x(i))=⎣⎢⎢⎢⎢⎢⎢⎡∑j=1keθ(j)x(i)eθ(1)x(i)∑j=1keθ(j)x(i)eθ(2)x(i)...∑j=1keθ(j)x(i)eθ(k)x(i)⎦⎥⎥⎥⎥⎥⎥⎤=∑j=1keθ(j)x(i)1⎣⎢⎢⎢⎡eθ(1)x(i)eθ(2)x(i)...eθ(k)x(i)⎦⎥⎥⎥⎤
损失函数类比我们的二分类损失函数:
仍先从单样本看起
二 分 类 损 失 函 数 : C o s t ( θ ) = − log ( h θ ( x ) ) i f y = 1 C o s t ( θ ) = − log ( 1 − h θ ( x ) ) i f y = 0 多 分 类 损 失 函 数 : C o s t ( θ ( 1 ) ) = − log ( h θ ( 1 ) ( x ) ) i f y = 1 C o s t ( θ ( 2 ) ) = − log ( h θ ( 2 ) ( x ) ) i f y = 2 . . . C o s t ( θ ( k ) ) = − log ( h θ ( k ) ( x ) ) i f y = k 二分类损失函数:\\ Cost(\theta)=-\log(h_\theta(x))\qquad\quad if\ y=1\\ Cost(\theta)=-\log(1-h_\theta(x))\quad if\ y=0\\ 多分类损失函数:\\ Cost(\theta^{(1)})=-\log(h_{\theta^{(1)}}(x))\qquad if\ y=1\\ Cost(\theta^{(2)})=-\log(h_{\theta^{(2)}}(x))\qquad if\ y=2\\ ...\\ Cost(\theta^{(k)})=-\log(h_{\theta^{(k)}}(x))\qquad if\ y=k\\ 二分类损失函数:Cost(θ)=−log(hθ(x))if y=1Cost(θ)=−log(1−hθ(x))if y=0多分类损失函数:Cost(θ(1))=−log(hθ(1)(x))if y=1Cost(θ(2))=−log(hθ(2)(x))if y=2...Cost(θ(k))=−log(hθ(k)(x))if y=k
对于二分类问题,我们可以使用y*log+(1-y)*log
的方法来解决y=0
和y=1
的情况,但是对于多分类,我们只能引入一个判断逻辑了。
J ( θ ) = C o s t ( θ ) = ∑ j = 1 k I { y = j } C o s t ( θ ( j ) ) = ∑ j = 1 k I { y = j } log ( h θ ( j ) ( x ) ) 其 中 I { x } = { 0 i f x = f a l s e 1 i f x = t u r e 就 是 I { x } 的 条 件 为 真 , 值 为 1 , 否 则 为 0. J(\theta)=Cost(\theta)=\sum_{j=1}^k I\{y=j\}Cost(\theta^{(j)})=\sum_{j=1}^k I\{y=j\}\log(h_{\theta^{(j)}}(x))\\ 其中I\{x\}=\left\{\begin{matrix} 0 & if\ x=false\\ 1 & if\ x=ture\\ \end{matrix}\right.就是I\{x\}的条件为真,值为1,否则为0. J(θ)=Cost(θ)=j=1∑kI{y=j}Cost(θ(j))=j=1∑kI{y=j}log(hθ(j)(x))其中I{x}={01if x=falseif x=ture就是I{x}的条件为真,值为1,否则为0.
对于多样本,只需要将单样本的代价函数加和起来即可:
J ( θ ) = − 1 m ∑ i = 1 m C o s t ( θ ) = − 1 m ∑ i = 1 m ∑ j = 1 k I { y ( i ) = j } C o s t ( θ ( j ) ) = − 1 m ∑ i = 1 m ∑ j = 1 k I { y ( i ) = j } log ( h θ ( j ) ( x ( i ) ) ) = − 1 m ∑ i = 1 m ∑ j = 1 k I { y ( i ) = j } log e θ ( j ) x ∑ l = 1 k e θ ( l ) x \begin{aligned} & J(\theta)=-\frac{1}{m}\sum_{i=1}^mCost(\theta)\\ &\quad =-\frac{1}{m}\sum_{i=1}^m\sum_{j=1}^k I\{y^{(i)}=j\}Cost(\theta^{(j)})\\ &\quad=-\frac{1}{m}\sum_{i=1}^m\sum_{j=1}^k I\{y^{(i)}=j\}\log(h_{\theta^{(j)}}(x^{(i)}))\\ &\quad=-\frac{1}{m}\sum_{i=1}^m\sum_{j=1}^k I\{y^{(i)}=j\}\log\frac{e^{\theta^{(j)}x}}{\sum_{l=1}^ke^{\theta^{(l)}x}}\\ \end{aligned} J(θ)=−m1i=1∑mCost(θ)=−m1i=1∑mj=1∑kI{y(i)=j}Cost(θ(j))=−m1i=1∑mj=1∑kI{y(i)=j}log(hθ(j)(x(i)))=−m1i=1∑mj=1∑kI{y(i)=j}log∑l=1keθ(l)xeθ(j)x
使用梯度下降求使得损失函数最小的θ。同步更新θ
考虑二分类梯度下降:
θ j : = θ j + α ∂ ∂ θ j J ( θ ) j ∈ [ 1 , n ] 是 特 征 的 个 数 \theta_j:=\theta_j+\alpha\frac{\partial}{\partial \theta_j}J(\theta)\\ j\in[1,n]是特征的个数 θj:=θj+α∂θj∂J(θ)j∈[1,n]是特征的个数
二分类梯度下降可以使用矩阵乘法,同步更新。
对于多分类问题,只需要依次计算各各分类的θ即可
对 于 { x ( i ) , y ( i ) } 样 本 中 , 预 测 y ( i ) ∈ [ 1 , k ] 是 k 个 分 类 , j ∈ [ 1 , n ] 是 特 征 数 对 于 P ( y ( i ) = 1 ∣ x , θ ) 的 情 况 : θ j ( 1 ) : = θ j ( 1 ) + α ∂ ∂ θ j ( 1 ) J ( θ ) . . . 对 于 P ( y ( i ) = l ∣ x , θ ) 的 情 况 : θ j ( l ) : = θ j ( l ) + α ∂ ∂ θ j ( l ) J ( θ ) . . . 对 于 P ( y ( i ) = k ∣ x , θ ) 的 情 况 : θ j ( k ) : = θ j ( k ) + α ∂ ∂ θ j ( k ) J ( θ ) 对于\{x^{(i)},y^{(i)}\}样本中,预测y^{(i)}\in[1,k]是k个分类,j\in[1,n]是特征数\\ 对于P(y^{(i)}=1|x,\theta)的情况:\theta_j^{(1)}:=\theta_j^{(1)}+\alpha\frac{\partial}{\partial \theta_j^{(1)}}J(\theta)\\ ...\\ 对于P(y^{(i)}=l|x,\theta)的情况:\theta_j^{(l)}:=\theta_j^{(l)}+\alpha\frac{\partial}{\partial \theta_j^{(l)}}J(\theta)\\ ...\\ 对于P(y^{(i)}=k|x,\theta)的情况:\theta_j^{(k)}:=\theta_j^{(k)}+\alpha\frac{\partial}{\partial \theta_j^{(k)}}J(\theta)\\ 对于{x(i),y(i)}样本中,预测y(i)∈[1,k]是k个分类,j∈[1,n]是特征数对于P(y(i)=1∣x,θ)的情况:θj(1):=θj(1)+α∂θj(1)∂J(θ)...对于P(y(i)=l∣x,θ)的情况:θj(l):=θj(l)+α∂θj(l)∂J(θ)...对于P(y(i)=k∣x,θ)的情况:θj(k):=θj(k)+α∂θj(k)∂J(θ)
求导:
θ j ( l ) : = θ j ( l ) + α ∂ ∂ θ j ( l ) J ( θ ) θ j ( l ) : = θ j ( l ) + α ∂ ( − 1 m ∑ i = 1 m ∑ p = 1 k I { y ( i ) = p } log ( h θ ( p ) ( x ( i ) ) ) ) ∂ θ j ( l ) θ j ( l ) : = θ j ( l ) − α 1 m ∑ i = 1 m [ x ( i ) ∗ ( 1 ∗ I { y ( i ) = l } − e θ j ( l ) x ∑ p = 1 k e θ j ( p ) x ) ] θ j ( l ) : = θ j ( l ) − α 1 m ∑ i = 1 m [ x ( i ) ∗ ( I { y ( i ) = l } − P ( y ( i ) = l ∣ x ( i ) , θ ) ) ] \begin{aligned} & \theta_j^{(l)}:=\theta_j^{(l)}+\alpha\frac{\partial}{\partial \theta_j^{(l)}}J(\theta)\\ & \theta_j^{(l)}:=\theta_j^{(l)}+\alpha\frac{\partial(-\frac{1}{m}\sum_{i=1}^m\sum_{p=1}^k I\{y^{(i)}=p\}\log(h_{\theta^{(p)}}(x^{(i)})))}{\partial \theta_j^{(l)}}\\ & \theta_j^{(l)}:=\theta_j^{(l)}-\alpha\frac{1}{m}\sum_{i=1}^m[x^{(i)}*(1*I\{y^{(i)}=l\}-\frac{e^{\theta^{(l)}_j x}}{\sum_{p=1}^k e^{\theta^{(p)}_jx}})]\\ & \theta_j^{(l)}:=\theta_j^{(l)}-\alpha\frac{1}{m}\sum_{i=1}^m[x^{(i)}*(I\{y^{(i)}=l\}-P(y^{(i)}=l|x^{(i)},\theta))]\\ \end{aligned} θj(l):=θj(l)+α∂θj(l)∂J(θ)θj(l):=θj(l)+α∂θj(l)∂(−m1∑i=1m∑p=1kI{y(i)=p}log(hθ(p)(x(i))))θj(l):=θj(l)−αm1i=1∑m[x(i)∗(1∗I{y(i)=l}−∑p=1keθj(p)xeθj(l)x)]θj(l):=θj(l)−αm1i=1∑m[x(i)∗(I{y(i)=l}−P(y(i)=l∣x(i),θ))]
这里的j表示的是第l种分类中底j个特征值.
通过l和j的组合,可以得到多分类问题l*j所有的θ权重.
下面就是完整的求导推导过程,如果不想看的可以直接跳到下一断,因为废话着实多
手动求导时,我习惯写作
θ ( l ) : = θ ( l ) + α ∂ ∂ θ ( l ) J ( θ ) \theta^{(l)}:=\theta^{(l)}+\alpha\frac{\partial}{\partial \theta^{(l)}}J(\theta)\\ θ(l):=θ(l)+α∂θ(l)∂J(θ)
省略了j,因为直接使用矩阵乘法,可以一步得出整个第l个分类的θ情况.还可避免变量过多导致的头昏眼花
下面有两种求导化简过程,(其实本质都一样,只是看那个更方便理解一点)
首先将求导公式变为这个式子:
∂ J ( θ ) ∂ θ ( l ) = ∂ ∂ θ ( l ) ( log e θ ( l ) x ∑ p = 1 k e θ ( p ) x ) \frac{\partial J(\theta)}{\partial \theta^{(l)}}=\frac{\partial}{\partial\theta^{(l)}}(\log\frac{e^{\theta^{(l)}x}}{\sum_{p=1}^k e^{\theta^{(p)}x}})\\ ∂θ(l)∂J(θ)=∂θ(l)∂(log∑p=1keθ(p)xeθ(l)x)
化简过程:
化简到这一步后,就可以比较方便的求导了
之后,我把I{y=j}省略了,其实每一项都是要乘进去的.
直接求导,用分式求导法.
先拆开,再求导
求完导后,即可考虑算法步骤了
算法步骤参考之前的二分类算法
S t e p 1 : 随 机 一 个 θ 矩 阵 S t e p 2 : 重 复 进 行 梯 度 下 降 求 取 θ 确 定 步 长 α 同 步 更 新 θ j ( l ) : = θ j ( l ) + α ∂ ∂ θ j ( l ) J ( θ ) S t e p 3 : 找 打 合 适 的 θ 终 止 循 环 \begin{aligned} & Step1:随机一个\theta矩阵\\ & Step2:重复进行梯度下降求取\theta\\ & \qquad 确定步长\alpha\\ & \qquad 同步更新\theta_j^{(l)}:=\theta_j^{(l)}+\alpha\frac{\partial}{\partial \theta_j^{(l)}}J(\theta)\\ & Step3:找打合适的\theta终止循环 \end{aligned} Step1:随机一个θ矩阵Step2:重复进行梯度下降求取θ确定步长α同步更新θj(l):=θj(l)+α∂θj(l)∂J(θ)Step3:找打合适的θ终止循环
根据以上分析,参考二分类问题的代码,依次进行功能实现.
在一个空白目录下,新建文件softmaxRegressionTrain.py文件
直接矩阵乘法求出分子矩阵,然后矩阵乘法求出分母矩阵,然后相除即可.
import numpy as np
def forecastFunction(theta,x):
'''
forecastFunction()函数将输入的x求预测
输入:theta模型(k*n)的矩阵
x变量(m*n)的矩阵
输出:预测值矩阵(m*k)
'''
m=np.shape(x)[0]
a=np.exp((x*(theta.T)))#得到预测值分子矩阵(m*k)
sum=a*np.mat(np.ones((k,1)))#得到分母矩阵(m*1)
for i in range(m):
a[i]=a[i]/sum[i]
return a
自行测试,输如果用theta全1的矩阵,应该结果全是一样的.
在拟合函数下继续写代价函数
直接将上面的公式翻译一下即可,非常简单
def errCost(fc,y):
'''
errCost()函数,通过预测输出和样本输出来计算代价
输入:fc一个m*k的预测矩阵
y是一个(m*1)的样本矩阵
输出:代价值
'''
m=np.shape(fc)[0]
k=np.shape(fc)[1]
sumCost=0.0
for i in range(m):
if (fc[i,y[i]])>0:
sumCost+=np.log(fc[i,y[i]])
else:
sumCost+=0
return sumCost/m
根据前文算法步骤,直接计算即可
这里计算的时候,我先全设为(0-P),对于(1-P)的我单独加上去,清晰很多.
def loopGradientDescent(alpha,x,y,k,cnt):
'''
loopGradientDescent()函数,用来循环梯度下降求解
输入:aplha步长
x一个m*n的样本矩阵
y一个m*1的样本输出矩阵
k多分类数量
cnt循环次数
输出:一个k*n的矩阵
'''
m=np.shape(x)[0]
n=np.shape(x)[1]
theta=np.mat(np.ones((k,n)))
for i in range(cnt):#迭代cnt次
fc=forecastFunction(theta,x)#获取预测数据m*k
sumCost=errCost(fc,y)#查看预测误差
fc=(-1)*fc#先都按(0-fc)算
for j in range(m):#符合条件的+1
fc[j,y[j]]+=1
theta=theta+(alpha/m)*(((x.T)*fc).T)#调用公式
if i%200==0:
print("第"+str(i)+"次迭代:")
print("误差:"+str(sumCost))
print("theta:")
print(theta)
return theta
以上就是softmax算法的所有代码了,我们将其补全(存取数据和模型)
数据随机使用我们之前写好的随机数据生成器,改一些参数就好了
机器学习入门实践–线性模型-分类算法-二分类问题(python)随机数据的代码,在这篇文章的中间 数据存取与模型存取的数据获取 段落地方.当然,也可以自己写随机数生成器.
继续接着上面的代码写
def loadData(fileName):
'''
loadData()通过文件名导入训练数据
输出:返回一个x矩阵m*n的
返回一个y矩阵m*1的
返回一个y的标签数目len
'''
f=open(fileName)
x=[]
y=[]
for line in f.readlines():
tmpX=[]
tmpX.append(1)
lines=line.strip().split("\t")
for i in range(len(lines)-1):
tmpX.append(float(lines[i]))
y.append(int(lines[-1]))
x.append(tmpX)
f.close()
return np.mat(x),np.mat(y).T,len(set(y))
def saveModel(fileName,theta):
'''
saveModel()函数将模型存入本地
输入:fileName文件名
theta一个m*k的矩阵
'''
f=open(fileName,"w")
m=np.shape(theta)[0]
k=np.shape(theta)[1]
for i in range(m):
tmpT=[]
for j in range(k):
tmpT.append(str(theta[i,j]))
f.write("\t".join(tmpT)+"\n")
f.close()
if __name__=='__main__':
#获取数据
x,y,k=loadData("trainData")
#获取模型
theta=loopGradientDescent(0.001,x,y,k,5000)
#保存模型
saveModel("ModelData",theta)
'''样例输出
第0次迭代:
误差:[[-1.38629436]]
theta:
[[0.99995 1.00028712 1.00021154]
[0.99998704 0.99975843 0.99844126]
[1.00001667 0.99988445 1.00145407]
[1.0000463 1.00007001 0.99989313]]
第200次迭代:
误差:[[-1.18197412]]
theta:
[[0.98882917 1.05378555 1.03128921]
[1.01666191 0.95677654 0.87092004]
[0.982151 0.97562871 1.08728472]
[1.01235792 1.0138092 1.01050603]]
第400次迭代:
误差:[[-1.13961024]]
theta:
[[0.97628497 1.10045183 1.04581596]
[1.04203359 0.91809883 0.82746232]
[0.95704909 0.95514268 1.10339652]
[1.02463234 1.02630666 1.02332519]]
.....
.....
第4200次迭代:
误差:[[-0.89919939]]
theta:
[[0.76006369 1.4816234 1.09019137]
[1.47815438 0.50354178 0.67924992]
[0.52692209 0.8719239 1.18748345]
[1.23485984 1.14291091 1.04307526]]
第4400次迭代:
误差:[[-0.89334303]]
theta:
[[0.75002682 1.49039632 1.09181997]
[1.4966069 0.49248418 0.67460443]
[0.50765156 0.87146402 1.19054465]
[1.24571472 1.14565547 1.04303095]]
第4600次迭代:
误差:[[-0.88772988]]
theta:
[[0.74008448 1.49865807 1.09344813]
[1.5147469 0.4820644 0.67002751]
[0.48864235 0.87106069 1.19355832]
[1.25652626 1.14821684 1.04296605]]
第4800次迭代:
误差:[[-0.88233867]]
theta:
[[0.73023336 1.50644708 1.09507391]
[1.53259155 0.47224084 0.66552003]
[0.46988391 0.8707044 1.19652528]
[1.26729118 1.15060768 1.04288078]]
'''
我们已经将训练好的模型保存了下来
接下来就是使用训练好的模型了
新建一个文件test.py,用来使用我们的模型
S t e p 1 : 导 入 我 们 训 练 好 的 逻 辑 回 归 模 型 ( 之 前 保 存 在 本 地 的 m o d e l D a t a 文 件 ) S t e p 2 : 导 入 测 试 集 数 据 , 我 们 要 拟 合 的 数 据 S t e p 3 : 按 照 回 归 模 型 对 数 据 进 行 预 测 S t e p 4 : 保 存 最 终 预 测 结 果 存 入 本 地 \begin{aligned} & Step1:导入我们训练好的逻辑回归模型(之前保存在本地的modelData文件)\\ & Step2:导入测试集数据,我们要拟合的数据\\ & Step3:按照回归模型对数据进行预测\\ & Step4:保存最终预测结果存入本地\\ \end{aligned} Step1:导入我们训练好的逻辑回归模型(之前保存在本地的modelData文件)Step2:导入测试集数据,我们要拟合的数据Step3:按照回归模型对数据进行预测Step4:保存最终预测结果存入本地
import numpy as np
import softmaxRegressionTrain as SRT
def loadModel(fileName):
'''
loadModel()函数,根据文件名提取出模型theta,并返回一个n*1的矩阵
输入:fileName文件名
输出:一个(k*n)的矩阵,作为模型
'''
f=open(fileName)
theta=[]
for line in f.readlines():#遍历文件每一行(这里只有一行)
tmpt=[]
lines=line.strip().split("\t")#格式化后,用\t分割字符串
for x in lines:
tmpt.append(float(x))#将每一行的每一个字符串转为浮点数保存入列表中
theta.append(tmpt)#将该行的值
f.close()
return np.mat(theta)
def loadData(fileName,n):
'''
loadData()函数,通过文件名获取文件的数据,最后输出一个m*n的矩阵,作为样本
输入:fileName文件名
输出:一个(m*n)的矩阵,作为样本
'''
f=open(fileName)
x=[]
for line in f.readlines():
tmpx=[]
lines=line.strip().split("\t")
if len(lines) != (n-1):#对于不合格的数据不要
continue
tmpx.append(1)#先加入一个常数项
for i in lines:#加入后续的特征值
tmpx.append(float(i))
x.append(tmpx)
f.close()
return np.mat(x)
直接使用我们的模型中的预测函数即可
def predict(x,theta):
'''
predict()调用训练模型来预测结果
输出:一个m*k的矩阵,表示的概率
'''
y=SRT.forecastFunction(theta,x)
return y
def saveY(fileName,y):
'''
保存结果
'''
f=open(fileName,"w")
m=np.shape(y)[0]
k=np.shape(y)[1]
for i in range(m):
for j in range(k):
f.write(str(y[i,j]))
f.write("\t")
f.write("\n")
f.close()
if __name__=="__main__":
#导入模型
theta=loadModel("modelData")
k=np.shape(theta)[0]
n=np.shape(theta)[1]
#导入数据
x=loadData("testData",n)
#预测结果
y=predict(x,theta)
#保存结果
saveY("predictY",y)
在softmax regression算法种存在着参数冗余问题.(换句话说,有些参数,向量是没有用处的)
参考书
P ( y ( i ) = j ∣ X ( i ) ; θ ) = e ( θ j − ψ ) T X ( i ) ∑ l = 1 k e ( θ l − ψ ) T X ( i ) = e θ j T X ( i ) ∗ e − ψ T X ( i ) ∑ l = 1 k e θ j T X ( i ) ∗ e − ψ T X ( i ) = e θ j T X ( i ) ∑ l = 1 k e θ j T X ( i ) \begin{aligned} P(y^{(i)}=j|X^{(i)};\theta) & =\frac{e^{(\theta_j-\psi)^TX^{(i)}}}{\sum^{k}_{l=1}e^{(\theta_l-\psi)^TX^{(i)}}}\\ & =\frac{e^{\theta_j^T X^{(i)}}*e^{-\psi^T X^{(i)}}}{\sum^{k}_{l=1}e^{\theta_j^T X^{(i)}}*e^{-\psi^T X^{(i)}}}\\ & =\frac{e^{\theta_j^T X^{(i)}}}{\sum^{k}_{l=1}e^{\theta_j^T X^{(i)}}} \end{aligned} P(y(i)=j∣X(i);θ)=∑l=1ke(θl−ψ)TX(i)e(θj−ψ)TX(i)=∑l=1keθjTX(i)∗e−ψTX(i)eθjTX(i)∗e−ψTX(i)=∑l=1keθjTX(i)eθjTX(i)
参数Θ减去了向量ψ之后对预测结果没有什么影响.
意思就是,这个模型中,存在多组最优解,即使训练后,去除某些向量,也是可以得出去除向量后的最优解的.
有了前面的二分类的基础,写多分类就简单多了.
其实和上一篇博客二分类一样,
完整代码放在了gitee中:机器学习入门实践: 机器学习入门实践