用Scikit-Learn进行Logistic回归
目录
绪论
Logistic回归是一种机器学习模型,它有助于预测一个事件(称为 "类")的概率。
在本教程中,我们将使用Scikit-Learn及其逻辑回归基元,根据睡眠时间和觉醒次数来预测一夜好眠的可能性。
输入
1import numpy as np
2import pandas as pd
3import matplotlib.pyplot as plt
4from sklearn.model_selection import train_test_split
5from sklearn.preprocessing import MinMaxScaler
6from sklearn.linear_model import LogisticRegression
7
8plt.rcParams['figure.figsize'] = [8, 7]
9plt.rcParams['figure.dpi'] = 100
Logistic回归模型
逻辑回归是一种模型,与常规的线性回归不同,它有助于预测某一类(如下雨)为真的概率,为1和0之间的数字。
X -> y,其中1.0 >= y >= 0.0
在典型的二元或二项分类中,特征与真值和假值有关,而不是连续值。结果从绝对真实(1.0)到绝对虚假(0.0)。
让我们开始行动吧。让我们考虑一个数据集,其中患有睡眠问题的病人报告他们睡了多少小时,晚上醒了多少次,然后,早上感觉如何,作为 "睡眠不好"(False)或 "睡眠好"(True)。
1np.random.seed(3)
2sleep_hours = np.linspace(1,9,100)
3awakenings = np.random.randint(1,6,size=1001)
4sleep_q = [ 6 + h + (np.random.rand()*3) - a
5 for (h,a) in zip(sleep_hours,awakenings) ]
6X = np.array([ [h,a] for (h,a) in zip(sleep_hours,awakenings) ])
7y = [ q >= 12 for q in sleep_q ]
8
9good = [ (h,a) for (h,a,y) in zip(sleep_hours,awakenings,y) if y]
10bad = [ (h,a) for (h,a,y) in zip(sleep_hours,awakenings,y) if not y]
11
12plt.scatter([ t[0] for t in good ], [ t[1] for t in good ],color='b',label='Slept Well')
13plt.scatter([ t[0] for t in bad ], [ t[1] for t in bad ],color='r',label='Slept Badly')
14plt.legend(loc='upper left')
15plt.xlabel('Sleep Hours')
16plt.ylabel('Awakenings')
17plt.yticks([1,2,3,4,5])
18plt.show()
在这个例子中,我们不会把数据集分成训练集和测试集,而是在整个数据集上训练模型。
1model = LogisticRegression().fit(X, y)
就这样了。我们现在可以审问这个数字了。常规的predict() 方法返回类,在本例中是一个bool 答案,而不是一个float 值。我们使用precit_proba() ,而不是获得每个类别的实际概率(在我们的例子中是False ,和True )。
**例1:**病人睡了3.2小时,醒了0次。他的睡眠好吗?
1model.predict([[3.2,0]])
array([False])
1model.predict_proba([[3.2,0]])
array([[0.89892622, 0.10107378]])
**例2:**病人睡了8小时,但醒了10次。她的睡眠好吗?
1model.predict([[8.0,10]])
array([False])
1model.predict_proba([[8.0,10]])
array([[9.99984809e-01, 1.51910314e-05]])
**例3:**病人睡了10个小时,醒了0次。她的睡眠质量好吗?
1model.predict([[10.0,0]])
array([ True])
1model.predict_proba([[10.0,0]])
array([[2.42600004e-04, 9.99757400e-01]])
在这组数据中,尽管是合成的,但有趣的是注意到觉醒的次数是如何影响晚上睡得好的机会的。这就是predict_proba() 产生的概率值的闪光之处。
1def probability(awakenings):
2 zero = [ [h,model.predict_proba([[h,awakenings]])[0][1]]
3 for h in np.linspace(0,12,12) ]
4 plt.plot([t[0] for t in zero], [t[1] for t in zero])
5 if awakenings >= 3:
6 plt.xlabel("Sleep hours")
7 if awakenings in [0,3]:
8 plt.ylabel("Sleep well probability")
9 plt.yticks([0.0,0.2,0.4,0.6,0.8,1])
10 plt.xticks([0,2,4,6,8,10,12])
11 plt.title("# Awakenings = {}".format(awakenings))
12
13for x in range (0,6):
14 plt.subplot(2, 3, x+1)
15 probability(x)
正则化
逻辑回归使用的是线性模型,它可以被规范化,就像产生连续值的常规回归模型一样。让我们先看一下我们正在研究的模型的类别边界,没有任何附加的惩罚措施。
1def show_class_boundary(models):
2 plt.scatter([ t[0] for t in good ], [ t[1] for t in good ],color='b',label='Slept Well')
3 plt.scatter([ t[0] for t in bad ], [ t[1] for t in bad ],color='r',label='Slept Badly')
4 plt.xlabel('Sleep Hours')
5 plt.ylabel('Awakenings')
6 plt.yticks([1,2,3,4,5])
7 for i,m in enumerate(models):
8 class_boundary = [ (h,a)
9 for h in np.linspace(0,10,200)
10 for a in np.linspace(0,6,200)
11 if abs((m.predict_proba([[h,a]])[0][1])-0.5)
12 <= 0.001 ]
13 plt.plot([ t[0] for t in class_boundary ], [ t[1] for t in class_boundary ],label="Class Boundary {}".format(i+1))
14 plt.legend(loc='upper left')
15
16show_class_boundary([model])
17
在上面的可视化图中,我们可以看到类的边界线至少包括一个红点。在现实世界中,这个模型实际上是几乎完美的,因为我们提供的合成数据集实际上是线性的。但是,假设我们希望这个逻辑回归的工作方式是,如果预测是真的,(病人睡得好),那么,就没有任何机会出现假阳性。
实现这一目标的方法是通过使用C 参数添加一个惩罚(默认为L2,但也可以选择L1)。在下面的例子中,我们设置了C=0.2 ,其效果是将类的边界向右推,使其不再覆盖红点。
1model2 = LogisticRegression(C=0.2).fit(X, y)
2show_class_boundary([model,model2])
我们提供的惩罚是很小的,所以它不会改变分数,因为它已经接近100%了。
1display(model.score(X, y))
2display(model2.score(X, y))
0.96
0.96
结论
Logistic回归是最简单的 "分类 "模型之一,当类之间的分离在某种程度上是线性的时候,它是最有用的。在未来的教程中,我们将探讨如何处理那些排列似乎更加随意的类。
在你离开之前
🤘 订阅我的100%无垃圾邮件的时事通讯!
电子邮件。