首页 > 编程知识 正文

python逻辑斯蒂回归,python逻辑或运算符

时间:2023-05-05 10:55:08 阅读:262826 作者:3890

为什么使用sigmoid函数

在上两节中已经说到,逻辑个性的可乐回归只是在线性回归的基础上套用了一个逻辑函数,并且也解释了,线性的原因。忘记的可以回顾一下。

下面我们再具体解释一下,为什么逻辑个性的可乐选择使用sigmoid函数。

为什么是sigmoid函数

假设数据集有n个独立的 特征,x1到xn为样本的n个特征。常规的回归算法的目标是拟合出一个多项式函数(线性函数),使得预测值与真实值的误差最小:


但是线性回归的鲁棒性比较差,可能会因为少数的噪音,导致模型不好,主要是因为线性模型对整个实数域的敏感性是一致的。我们需要解决的是:对于大部分集中的数据是敏感的,而对于边缘的少数数据是不敏感的。另一方面,我们希望我们的模型能够具有很好的逻辑判断性质,最好是能够直接表达具有特征X的样本被分到某类的概率是多大,把概率范围控制在[0,1]。比如,假设我们的模型为f(x),当f(x)>0.5的时候,把样本X归为正类;当f(x)<0.5的时候,把样本X归为负类。那么考虑有没有这样的一种函数,可以满足我们以上的两种需求呢?

这个时候我们的救星出现了:sigmoid函数!

首先,给书sigmoid函数的定义:

然后我们看一下sigmoid函数图像:

a.通过图像可以看出当x在0点附近的时候,函数图像比较陡峭,而在横坐标轴两端处,即x>>0或者x<<0的时候,图像比较平稳。这也就说函数对于0值附近的数据比较敏感,对于边缘数据不敏感。这满足了我们的第一个需求。b. 通过sigmoid函数的性质,可以知道:其定义域在全体实数,值域在[0,1]之间,并且当x>0的时候f(x)>0.5(正类);当x=0的时候f(x)=0.5(中性);当x<0的时候f(x)<0.5(负类)。这满足了我们的第二个需求。就它了! 如何将线性函数转变为sigmoid函数

设线性函数为f(x),令P(x)=P(Y=1|X=x):具有特征x的样本被分到类别1的概率,则,被定义为让步比(odds ratio)。则就为我们想要线性函数f(x)达到我们想要的概率结果。

例如,当P(x)>0.5的时候,P(x)/[1-P(x)]>1,则f(x)>0,反过来也就是说,只要我们的线性函数满足f(x)>0就会有P(x)>0.5,此时X属于正类。同理,当f(x)<0的时候就会有P(x)<0.5,此时x属于负类,和上一部分讲解的sigmoid函数性质完全一致。

下面 我们就进行转换:

设:

我们把P(x)解出来:

则P(x)就是我们想要的一种概率模型,也就是我们所说的逻辑个性的可乐回归模型,在此也就说明了逻辑个性的可乐回归模型是一种概率模型。

python实现 #算法一 调用sklearn里面的方法# _*_ encoding:utf-8 _*_from matplotlib import pyplotimport scipy as spimport numpy as npfrom matplotlib import pylabfrom sklearn.cross_validation import train_test_splitfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.metrics import precision_recall_curvefrom sklearn.metrics import classification_reportfrom sklearn.linear_model import LogisticRegressionimport timestart_time=time.time()#绘制R/p曲线def plot_pr(auc_score,precision,recall,label=None): pylab.figure(num=None, figsize=(6, 5)) pylab.xlim([0.0, 1.0]) pylab.ylim([0.0, 1.0]) pylab.xlabel('Recall') pylab.ylabel('Precision') pylab.title('P/R (AUC=%0.2f) / %s' % (auc_score, label)) pylab.fill_between(recall, precision, alpha=0.5) pylab.grid(True, linestyle='-', color='0.75') pylab.plot(recall, precision, lw=1) pylab.show()#读取movie_data=sp.load('move_data.npy')movie_target=sp.load('move_target.npy')x=movie_datay=movie_target#向量空间模型,count_vec = TfidfVectorizer(binary = False, decode_error = 'ignore', stop_words = 'english')average = 0testNum = 10#注意,训练样本调用fit_transform接口,测试样本调用的是transform接口for i in range(0,testNum): #加载数据集,切分数据集80%训练,20%测试 x_train, x_test, y_train, y_test = train_test_split(movie_data, movie_target, test_size = 0.2) x_train = count_vec.fit_transform(x_train) x_test = count_vec.transform(x_test) #训练LR分类器 clf=LogisticRegression() clf.fit(x_train,y_train) y_pred=clf.predict(x_test) p=np.mean(y_pred==y_test) print '第%d次测试的准确率为:%.5f'%(i,p) average+=p#精确率与召回率#answer = clf.predict_proba(x_test)[:,0]#属于第neg类的概率answer = clf.predict_proba(x_test)[:,1]#属于第pos类的概率#这个地方可以查看官方文档,precision, recall, thresholds = precision_recall_curve(y_test, answer)#thresholds对应着一个向量,个数为answer中不重复的值的个数,每个位置上的值对应着一个threshold,并且是越来越大#precision 和recall也是一个向量,个数比thresholds多一个,precision最后一个为1,recall最后一个值为0,确保图像从x轴=0开始#precision每个值对应着,当阈值为thresholds对应位置值的时候的准确度#例如:当取值取thresholds[0]的时候,precision[0]表示所有的训练集所对应的准确率recall[0]表示召回率report = answer > 0.5#这里的0.5可以换为其他值#我们通常使用0.5来划分两类数据,但是我们可以根据P/R图分析,选择一个合适的优秀的阈值。#print reportprint(classification_report(y_test, report, target_names = ['neg', 'pos']))print("平均精确度为:", average/testNum)print("花费的时间为:", time.time() - start_time)plot_pr(0.6, precision, recall, "pos")

实验结果:

第0次测试的准确率为:0.81071第1次测试的准确率为:0.79643第2次测试的准确率为:0.79643第3次测试的准确率为:0.80000第4次测试的准确率为:0.80714第5次测试的准确率为:0.81071第6次测试的准确率为:0.75714第7次测试的准确率为:0.78214第8次测试的准确率为:0.78214第9次测试的准确率为:0.81429 precision recall f1-score support neg 0.84 0.79 0.81 145 pos 0.79 0.84 0.81 135avg / total 0.82 0.81 0.81 280平均精度率为: 0.795714285714花费时间为: 12.1490001678

通过上图可以看出,如果选择的阈值过低,那么更多的测试样本都将分为1类,因此召回率得到提升,但是要牺牲相应的准确率。
注意precision_recall_curve()方法中的thresholds中的阈值是逐渐增大的,对应到图像是就会,x轴从左到右对应的阈值是逐渐减小的。

# -*- encoding:utf-8 -*-import matplotlib.pyplot as pltfrom matplotlib import animationimport numpy as np#加载数据集def loadDataSet(): ''' :return: 输入向量矩阵和输出向量 ''' dataMat=[] labelMat=[] fr=open('test.txt','r')#一共有三列,每一列为x1,x2,Y for line in fr.readlines(): lineArr=line.strip().split('##') #注意在这里将字符串转换成float型的时候总是遇到问题 #感觉每一行的开头存在其他字符,所以我们多添加了一列“##”分隔符,是的第一个有效数字从第二个开始 dataMat.append([1.0,float(lineArr[1]),float(lineArr[2])])#设x0为1,构成拓展之后的输入向量 labelMat.append(int(lineArr[3])) return dataMat,labelMat#可视化数据,画出数据集合逻辑个性的可乐最佳回归直线def plotBestFit(weights): dataMat,labelMat=loadDataSet() dataArr=np.array(dataMat) n=dataArr.shape[0] x1=[] y1=[] x2=[] y2=[] for i in range(n): if int(labelMat[i])==1: x1.append(dataArr[i,1]) y1.append(dataArr[i,2]) else: x2.append(dataArr[i,1]) y2.append(dataArr[i,2]) fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(x1,y1,s=30,c='red',marker='s') ax.scatter(x2,y2,s=30,c='green',) if weights is not None: x=np.arange(-3.0,3.0,0.1) y=(-weights[0]-weights[1]*x)/weights[2]# #令w0*x0 + w1*x1 + w2*x2 = 0,其中x0=1,解出x1和x2的关系 ax.plot(x,y) plt.xlabel('X1') plt.ylabel('X2') plt.show()def sigmoid(inX): return 1.0/(1+np.exp(-inX))#逻辑斯提回归梯度上升批量算法,静态展示def gradAscent_static(dataMatIn,classLabels): ''' :param dataMatIn: 输入X矩阵,每一行代表一个实例,每一列分别是x0,x1,x2 :param classLabels: 类别标签组成的向量 :return: 权值向量 ''' dataMatrix=np.mat(dataMatIn)#转换为numpy矩阵数据类型,(100,3) labelMat=np.mat(classLabels).transpose()#转换为numpy矩阵数据类型,(100,1) m,n=dataMatrix.shape alpha=0.001 maxCycles=500 weights=np.ones((n,1))#(3,1) for k in range(maxCycles): h=sigmoid(dataMatrix*weights) error=(labelMat-h)#向量减法 weights+=alpha*dataMatrix.transpose()*error#矩阵内积 return weightsdef draw_line(weights,lines): x = np.arange(-5.0, 5.0, 0.1) y = (-weights[0]-weights[1]*x)/weights[2] #令w0*x0 + w1*x1 + w2*x2 = 0,其中x0=1,解出x1和x2的关系 lines.set_data(x, y) return linesdef main1():#实现批量梯度上升,展示静态图像 datas,labels=loadDataSet() weights=gradAscent_static(datas,labels) plotBestFit(weights)#静态图if __name__ == '__main__': main1()

实验结果:

最终得到的权重向量为: [[ 4.12414349] [ 0.48007329] [-0.6168482 ]]

所谓的不平凡就是平凡的N次幂 ---------By Ada

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。