Logistic回归多分类之鸢尾花
来源:互联网 发布:新倩女幽魂网游mac版 编辑:程序博客网 时间:2024/04/25 19:43
作者:金良(golden1314521@gmail.com) csdn博客: http://blog.csdn.net/u012176591
- 多项逻辑回归模型原理
- 鸢尾花数据可视化
- 算法实现代码
- 混淆矩阵
- 进一步封装
1.多项逻辑回归模型原理
逻辑回归模型是二分类模型,用于二分类问题。可以将其推广为多项逻辑回归模型(multi-nominal logistic regression model),用于多分类。
假设类别
似然函数为
其中
对似然函数取对数,然后取负,得到
L(w)=−1N∑i=1N∑k=1KykilogP(yi=k|xi)=−1N∑i=1N(∑k=1K−1ykilogexp(wk⋅xi)1+∑K−1j=1exp(wj⋅xi)+yKilog11+∑K−1j=1exp(wj⋅xi))=−1N∑i=1N(∑k=1K−1yki(wk⋅xi−log(1+∑j=1K−1exp(wj⋅xi)))−yKilog(1+∑j=1K−1exp(wj⋅xi)))=1N∑i=1N(∑k=1Kykilog(1+∑j=1K−1exp(wj⋅xi))−∑k=1K−1ykiwk⋅xi)
考虑到过拟合的发生,对
∑K−1k=1|wk|22σ2
则
L(w)=1N∑i=1N(∑k=1Kykilog(1+∑j=1K−1exp(wj⋅xi))−∑k=1K−1ykiwk⋅xi)+∑k=1K−1|wk|22σ2
对
∂L(w)wk=1N∑i=1Nexp(wk⋅xi)1+∑K−1k=1exp(wk⋅xi)⋅xi−1N∑i=1Nykixi+wkσ2=1N∑i=1NP(yi=k|xi)⋅xi−1N∑i=1Nykixi+wkσ2
第一项
接下来用梯度下降法对参数
2.鸢尾花数据可视化
作图代码如下:
import numpy as npfrom mpl_toolkits.mplot3d import Axes3Dimport matplotlib.pyplot as pltimport itertools as itimport matplotlib as mpl#mpl.rcParams['xtick.labelsize'] = 6 #mpl.rcParams['ytick.labelsize'] = 6mpl.rcParams['axes.labelsize'] = 6 #设置所有坐标的刻度的字体大小attributes = ['SepalLength','SepalWidth','PetalLength','PetalWidth'] #鸢尾花的四个属性名comb = list(it.combinations([0,1,2,3],3)) # 每幅图挑出三个属性datas = []labels = []with open('Iris.txt','r') as f: for line in f: linedata = line.split(' ') datas.append(linedata[:-1]) #前4列是4个属性的值 labels.append(linedata[-1].replace('\n','')) #最后一列是类别datas = np.array(datas)datas = datas.astype(float) #将二维的字符串数组转换成浮点数数组labels = np.array(labels)kinds = list(set(labels)) #3个类别的名字列表fig = plt.figure()plt.title(u'鸢尾花数据的可视化显示',{'fontname':'STFangsong','fontsize':10})for k in range(4): ax = fig.add_subplot(int('22'+str(k+1)), projection='3d') for label,color,marker in zip(kinds,['r','b','k','y','c','g'],['s','*','o','^']): data = datas[labels == label ] for i in range(data.shape[0]): if i == 0: #对第一个点标记一个label属性,用于图例的显示,注意label不能设置多次,否则会重复显示 ax.plot([data[i,comb[k][0]]], [data[i,comb[k][1]]], [data[i,comb[k][2]]], color=color,marker = marker,markersize=3,label = label,linestyle = 'None') else: ax.plot([data[i,comb[k][0]]], [data[i,comb[k][1]]], [data[i,comb[k][2]]], color=color,marker = marker,markersize=3,linestyle = 'None') ax.legend(loc="upper left",prop={'size':8},numpoints=1) #图例的放置位置和字体大小 ax.set_xlabel(attributes[comb[k][0]],fontsize=8) #设置坐标的标签为属性名 ax.set_ylabel(attributes[comb[k][1]],fontsize=8) ax.set_zlabel(attributes[comb[k][2]],fontsize=8) ax.set_xticks(np.linspace(np.min(datas[:,comb[k][0]]),np.max(datas[:,comb[k][0]]),3)) #设置坐标的刻度 ax.set_yticks(np.linspace(np.min(datas[:,comb[k][1]]),np.max(datas[:,comb[k][1]]),3)) ax.set_zticks(np.linspace(np.min(datas[:,comb[k][2]]),np.max(datas[:,comb[k][2]]),3)) plt.subplots_adjust(wspace = 0.1,hspace=0.1) #子图之间的空间大小savefig('Iris.png',dpi=700,bbox_inches='tight')plt.show()
3.算法实现代码
attributes = ['SepalLength','SepalWidth','PetalLength','PetalWidth'] #鸢尾花的四个属性名datas = []labels = []with open('Iris.txt','r') as f: for line in f: linedata = line.split(' ') datas.append(linedata[:-1]) #前4列是4个属性的值 labels.append(linedata[-1].replace('\n','')) #最后一列是类别datas = np.array(datas)datas = datas.astype(float) #将二维的字符串数组转换成浮点数数组labels = np.array(labels)kinds = list(set(labels)) #3个类别的名字列表means = datas.mean(axis=0) #各个属性的均值stds = datas.std(axis=0) #各个属性的标准差N,M = datas.shape[0],datas.shape[1]+1 #N是样本数,M是参数向量的维K = 3 #K是类别数data = np.ones((N,M))data[:,1:] = (datas - means)/stds #对原始数据进行标准差归一化W = np.zeros((K-1,M)) # 存储参数矩阵priorEs = np.array([1.0/N*np.sum(data[labels == kinds[i]],axis=0) for i in range(K-1)]) #各个属性的先验先验期望值liklist = []for it in range(1000): lik = 0 # 当前的对数似然函数值 for k in range(K-1):#似然函数值的第一部分 lik -= np.sum(np.dot(W[k],data[labels == kinds[k]].transpose())) lik += 1.0/N*np.sum(np.log(np.sum(np.exp(np.dot(W,data.transpose())),axis = 0) +1)) #似然函数的第二部分 liklist.append(lik) # wx = np.exp(np.dot(W,data.transpose())) probs = np.divide(wx,1+np.sum(wx,axis=0).transpose()) #K-1*N的矩阵 posteriorEs = 1.0/N*np.dot(probs,data) #各个属性的后验期望值 gradients = posteriorEs - priorEs + 1.0/100 *W #梯度,最后一项是高斯项,防止过拟合 W -= gradients #对参数进行修正#probM每行三个元素,分别表示data中对应样本被判给三个类别的概率probM = np.ones((N,K))probM[:,:-1] = np.exp(np.dot(data,W.transpose()))probM /= np.array([np.sum(probM,axis = 1)]).transpose() #得到概率predict = np.argmax(probM,axis = 1).astype(int) #取最大概率对应的类别#rights列表储存代表原始标签数据的序号,根据labels数据生成rights = np.zeros(N) rights[labels == kinds[1]] =1rights[labels == kinds[2]] =2rights = rights.astype(int)print '误判的样本的个数:%d\n'%np.sum(predict != rights) #误判的个数
该算法的收敛性如下图所示:
4.混淆矩阵
#输出混淆矩阵K = np.shape(list(set(rights).union(set(predict))))[0]matrix = np.zeros((K,K))for righ,predic in zip(rights,predict): matrix[righ,predic] += 1print "%-12s" % ("类别"),for i in range(K): print "%-12s" % (kinds[i]), print '\n',for i in range(K): print "%-12s" % (kinds[i]), for j in range(K): print "%-12d" % (matrix[i][j]), print '\n',
上述混淆矩阵(confusion matrix)的行表示真实类别,列代表模型输出类别。可知,类setosa
的样本没有误判为其它类别,而且其它类别的样本没有误判为类 setosa
的,也就是说,我们训练出的模型没有将类setosa
的样本与其它类的样本混淆;4个versicolor
样本被误判为’virginica’ , 4个’virginica’样本被误判为versicolor
。总体看来,分类效果还是不错的。
5.进一步封装
def LogisticRegression(datas,labels): kinds = list(set(labels)) #3个类别的名字列表 means = datas.mean(axis=0) #各个属性的均值 stds = datas.std(axis=0) #各个属性的标准差 N,M = datas.shape[0],datas.shape[1]+1 #N是样本数,M是参数向量的维 K = np.shape(list(set(labels)))[0] #K是类别数 data = np.ones((N,M)) data[:,1:] = (datas - means)/stds #对原始数据进行标准差归一化 W = np.zeros((K-1,M)) # 存储参数矩阵 priorEs = np.array([1.0/N*np.sum(data[labels == kinds[i]],axis=0) for i in range(K-1)]) #各个属性的先验先验期望值 for it in range(1000): wx = np.exp(np.dot(W,data.transpose())) probs = np.divide(wx,1+np.sum(wx,axis=0).transpose()) #K-1*N的矩阵 posteriorEs = 1.0/N*np.dot(probs,data) #各个属性的后验期望值 gradients = posteriorEs - priorEs + 1.0/100 *W #梯度,最后一项是高斯项,防止过拟合 W -= gradients #对参数进行修正 #probM每行三个元素,分别表示data中对应样本被判给三个类别的概率 probM = np.ones((N,K)) probM[:,:-1] = np.exp(np.dot(data,W.transpose())) probM /= np.array([np.sum(probM,axis = 1)]).transpose() #得到概率 return probMif __name__ == "__main__": datas = [] labels = [] with open('Iris.txt','r') as f: for line in f: linedata = line.split(' ') datas.append(linedata[:-1]) #前4列是4个属性的值 labels.append(linedata[-1].replace('\n','')) #最后一列是类别 datas = np.array(datas) datas = datas.astype(float) #将二维的字符串数组转换成浮点数数组 labels = np.array(labels) kinds = list(set(labels)) #3个类别的名字列表 #LogisticRegression可以接受不同个数的类别数据,这里用元数据的子集(两个类别的样本)来测试 m,n = 1,2 sel = np.array(list(where(labels == kinds[m])[0])+(list(where(labels == kinds[n])[0]))) slabels = labels[sel] sdatas = datas[sel] probM = LogisticRegression(sdatas,slabels) print probM
1 0
- Logistic回归多分类之鸢尾花
- Logistic回归实现鸢尾花分类
- 分类数据之logistic回归
- 分类算法之logistic 回归模型
- 机器学习之logistic回归与分类
- 机器学习:多分类的logistic回归
- SPSS实例教程:有序多分类Logistic回归
- Logistic回归分类
- logistic回归分类
- logistic回归分类
- Python Logistic 回归分类
- 分类和Logistic回归
- 分类算法:Logistic回归
- 初识机器学习之决策树对鸢尾花进行分类
- linear regression for classification +随机梯度下降+多分类之logistic回归+多分类之线性分类投票法
- logistic regression 处理鸢尾花数据集
- 第三讲.Classification and logistic regression (分类及logistic回归 / 二分类和多分类)
- [学习笔记]分类算法之logistic 回归模型
- leetcode--Binary Tree Preorder Traversal
- jQuery跨任何域
- HttpClient的认证(转载)
- Linux内核空间与用户空间极其信息交互
- mysql 分区
- Logistic回归多分类之鸢尾花
- Android主题和样式
- 黑马程序员——java基础——String类,正则表达式
- android中string.xml中%1$s、%1$d等的用法
- Google插件switchysharp的用法
- 【机器学习】机器学习(十二、十三):K-means算法、高斯混合模型
- IOS开发学习实例之三---应用管理器
- Java小白手记:SSH
- 用nginx-gridFS读取MongoDB的图片及文件(为什么你老是配不成功?)