您现在的位置是:首页 > 文章详情

机器学习5- 对数几率回归+Python实现

日期:2020-04-25点击:461

机器学习5- 对数几率回归+Python实现

目录

  1. 对数几率回归
    1.1 求解 ω 和 b
  2. 对数几率回归进行垃圾邮件分类
    2.1 垃圾邮件分类

2.2 模型评估
混淆举证
精度
交叉验证精度
准确率召回率
F1 度量
ROC AUC

  1. 对数几率回归
    考虑二分类任务,其输出标记 y∈{0,1}y∈{0,1},记线性回归模型产生的预测值 z=wTx+bz=wTx+b 是实值,于是我们需要一个将实值 zz 转换为 0/10/1 的 g−(⋅)g−(⋅)。

最理想的单位阶跃函数(unit-step function)

y=⎧⎩⎨0,0.5,1,z<0z=0z>0(1.1)(1.1)y={0,z<00.5,z=01,z>0
并不是连续函数,因此不能作为 g−(⋅)g−(⋅) 。于是我们选用对数几率函数(logistics function)作为单位阶跃函数的替代函数(surrogate function):

y=11+e−z(1.2)(1.2)y=11+e−z
如下图所示:

对数几率函数是 Sigmoid 函数(即形似 S 的函数)的一种。

将对数几率函数作为 g−(⋅)g−(⋅) 得到

y=11+e−(wTx+b)(1.3)(1.3)y=11+e−(wTx+b)
lny1−y=wTx+b(1.4)(1.4)ln⁡y1−y=wTx+b
若将 yy 视为样本 xx 为正例的可能性,则 1−y1−y 是其为反例的可能性,两者的比值为

y1−y(1.5)(1.5)y1−y
称为几率(odds),反映了 xx 作为正例的相对可能性。对几率取对数得到对数几率(log odds,或 logit):

lny1−y(1.6)(1.6)ln⁡y1−y
所以,式 (1.3) 实际上是用线性回归模型的预测结果取逼近真实标记的对数几率,因此其对应的模型又称为对数几率回归(logistic regression, 或 logit regression)。

这种分类学习方法直接对分类可能性进行建模,无需事先假设数据分布,避免了假设分布不准确带来的问题;
它能得到近似概率预测,这对需要利用概率辅助决策的任务很有用;
对率函数是任意阶可导的凸函数,有很好的数学性质,许多数值优化算法都可直接用于求解最优解。

1.1 求解 ω 和 b
将式 (1.3) 中的 yy 视为类后验概率估计 p(y=1|x)p(y=1|x),则式 (1.4) 可重写为

lnp(y=1|x)p(y=0|x)=wTx+b(1.7)(1.7)ln⁡p(y=1|x)p(y=0|x)=wTx+b

p(y=1|x)=ewTx+b1+ewTx+b(1.8)(1.8)p(y=1|x)=ewTx+b1+ewTx+b
p(y=0|x)=11+ewTx+b(1.9)(1.9)p(y=0|x)=11+ewTx+b
通过极大似然法(maximum likelihood method)来估计 ww 和 bb 。

给定数据集 {(xi,yi)}mi=1{(xi,yi)}i=1m,对率回归模型最大化对数似然(log-likelihood):

ℓ(w,b)=∑i=1mlnp(yi|xi;w,b)(1.10)(1.10)ℓ(w,b)=∑i=1mln⁡p(yi|xi;w,b)
即令每个样本属于其真实标记的概率越大越好。

令 β=(w;b)β=(w;b),x^=(x;1)x^=(x;1),则 wTx+bwTx+b 可简写为 βTx^βTx^。再令 p1(x^;β)=p(y=1|x^;β)p1(x^;β)=p(y=1|x^;β),p0(x^;β)=p(y=0|x^;β)=1−p1(x^;β)p0(x^;β)=p(y=0|x^;β)=1−p1(x^;β) 。则式 (1.10) 可简写为:

p(yi|xi;w,b)=yip1(x^;β)+(1−yi)p0(x^;β)(1.11)(1.11)p(yi|xi;w,b)=yip1(x^;β)+(1−yi)p0(x^;β)
将式 (1.11) 带入 (1.10),并根据式 (1.8) 和 (1.9) 可知,最大化式 (1.10) 等价于最小化

ℓ(β)=∑i=1m(−yiβTx^i+ln(1+eβT+x^i))(1.12)(1.12)ℓ(β)=∑i=1m(−yiβTx^i+ln⁡(1+eβT+x^i))
式 (1.12) 是关于 ββ 的高阶可导凸函数,根据凸优化理论,经典的数值优化算法如梯度下降法(gradient descent method)、牛顿法(Newton method)等都可求得其最优解,于是得到:

β∗=arg min βℓ(β)(1.13)(1.13)β∗=arg min βℓ(β)
以牛顿法为例, 其第 t+1t+1 轮迭代解的更新公式为:

βt+1=βt−(∂2ℓ(β)∂β ∂βT)−1∂ℓ(β)∂β(1.14)(1.14)βt+1=βt−(∂2ℓ(β)∂β ∂βT)−1∂ℓ(β)∂β
其中关于 ββ 的一阶、二阶导数分别为:

∂ℓ(β)∂β=−∑i=1mx^i(yi−p1(x^i;β))(1.15)(1.15)∂ℓ(β)∂β=−∑i=1mx^i(yi−p1(x^i;β))
∂2ℓ(β)∂β∂βT=∑i=1mx^ix^Tip1(x^i;β)(1−p1(x^i;β))(1.16)(1.16)∂2ℓ(β)∂β∂βT=∑i=1mx^ix^iTp1(x^i;β)(1−p1(x^i;β))

  1. 对数几率回归进行垃圾邮件分类
    2.1 垃圾邮件分类

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.feature_extraction.text import TfidfVectorizer
from matplotlib.font_manager import FontProperties
df = pd.read_csv("SMSSpamCollection", delimiter='t', header=None)
df.head()

print("spam 数量: ", df[df[0] == 'spam'][0].count())
print("ham 数量: ", df[df[0] == 'ham'][0].count())
spam 数量: 747
ham 数量: 4825
X_train_raw, X_test_raw, y_train, y_test = train_test_split(df[1], df[0])

计算TF-IDF权重

vectorizer = TfidfVectorizer()
X_train = vectorizer.fit_transform(X_train_raw)
X_test = vectorizer.transform(X_test_raw)

建立模型

classifier = LogisticRegression()
classifier.fit(X_train, y_train)
y_preds = classifier.predict(X_test)
for i, y_pred in enumerate(y_preds[-10:]):

print("预测类型: %s -- 信息: %s" % (y_pred, X_test_raw.iloc[i]))

预测类型: ham -- 信息: Aight no rush, I'll ask jay
预测类型: ham -- 信息: Sos! Any amount i can get pls.
预测类型: ham -- 信息: You unbelievable faglord
预测类型: ham -- 信息: Carlos'll be here in a minute if you still need to buy
预测类型: spam -- 信息: Meet after lunch la...
预测类型: ham -- 信息: Hey tmr maybe can meet you at yck
预测类型: ham -- 信息: I'm on da bus going home...
预测类型: ham -- 信息: O was not into fps then.
预测类型: ham -- 信息: Yes..he is really great..bhaji told kallis best cricketer after sachin in world:).very tough to get out.
预测类型: ham -- 信息: Did you show him and wot did he say or could u not c him 4 dust?
2.2 模型评估
混淆举证
test = y_test
test[test == "ham"] = 0
test[test == "spam"] = 1

pred = y_preds
pred[pred == "ham"] = 0
pred[pred == "spam"] = 1
from sklearn.metrics import confusion_matrix
test = test.astype('int')
pred = pred.astype('int')
confusion_matrix = confusion_matrix(test.values, pred)
print(confusion_matrix)
plt.matshow(confusion_matrix)
font = FontProperties(fname=r"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc")
plt.title(' 混淆矩阵',fontproperties=font)
plt.colorbar()
plt.ylabel(' 实际类型',fontproperties=font)
plt.xlabel(' 预测类型',fontproperties=font)
plt.show()
[[1191 1]
[ 50 151]]

精度
from sklearn.metrics import accuracy_score

print(accuracy_score(test.values, pred))
0.9633883704235463
交叉验证精度
df = pd.read_csv("sms.csv")
df.head()

X_train_raw, X_test_raw, y_train, y_test = train_test_split(df['message'], df['label'])
vectorizer = TfidfVectorizer()
X_train = vectorizer.fit_transform(X_train_raw)
X_test = vectorizer.transform(X_test_raw)
classifier = LogisticRegression()
classifier.fit(X_train, y_train)
scores = cross_val_score(classifier, X_train, y_train, cv=5)
print(' 精度:',np.mean(scores), scores)
精度: 0.9562200956937799 [0.94736842 0.95933014 0.95574163 0.95574163 0.96291866]
准确率召回率
precisions = cross_val_score(classifier, X_train, y_train, cv=5, scoring='precision')
print('准确率:', np.mean(precisions), precisions)
recalls = cross_val_score(classifier, X_train, y_train, cv=5, scoring='recall')
print('召回率:', np.mean(recalls), recalls)
准确率: 0.9920944081237428 [0.98550725 1. 1. 0.98701299 0.98795181]
召回率: 0.6778796653796653 [0.61261261 0.69642857 0.66964286 0.67857143 0.73214286]
F1 度量
f1s = cross_val_score(classifier, X_train, y_train, cv=5, scoring='f1')
print(' 综合评价指标:', np.mean(f1s), f1s)
综合评价指标: 0.8048011339652206 [0.75555556 0.82105263 0.80213904 0.8042328 0.84102564]
ROC AUC
from sklearn.metrics import roc_curve, auc
predictions = classifier.predict_proba(X_test)
false_positive_rate, recall, thresholds = roc_curve(y_test, predictions[:, 1])
roc_auc = auc(false_positive_rate, recall)
plt.title('Receiver Operating Characteristic')
plt.plot(false_positive_rate, recall, 'b', label='AUC = %0.2f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.ylabel('Recall')
plt.xlabel('Fall-out')
plt.show()

原文地址https://www.cnblogs.com/raina/p/12777725.html

原文链接:https://yq.aliyun.com/articles/757579
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章