# Import necessary packagesimport pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('ggplot')from sklearn import datasets
from sklearn import linear_model
import numpy as np
# Load data
boston = datasets.load_boston()
yb = boston.target.reshape(-1,1)
Xb = boston['data'][:,5].reshape(-1,1)# Plot data
plt.scatter(Xb,yb)
plt.ylabel('value of house /1000 ($)')
plt.xlabel('number of rooms')# Create linear regression object
regr = linear_model.LinearRegression()# Train the model using the training sets
regr.fit( Xb, yb)# Plot outputs
plt.scatter(Xb, yb, color='black')
plt.plot(Xb, regr.predict(Xb), color='blue',
linewidth=3)
plt.show()技术支持
# Import necessary modulesfrom sklearn import linear_model
from sklearn.cross_validation import train_test_split
# Load data
df = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv ', sep =';')
X = df.drop('quality',1).values #drop target variable
y1 = df['quality'].values
y = y1 <=5# is the rating <= 5?# plot histograms of original target variable# and aggregated target variable
plt.figure(figsize=(20,5));
plt.subplot(1,2,1);
plt.hist(y1);
plt.xlabel('original target value')
plt.ylabel('count')
plt.subplot(1,2,2);
plt.hist(y)
plt.xlabel('aggregated target value')
plt.show()技术支持
现在让我们运行逻辑回归,看看表现如何!
# Split the data into test and training sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)#initial logistic regression model
lr = linear_model.LogisticRegression()# fit the model
lr = lr.fit(X_train, y_train)print('Logistic Regression score for training set: %f'% lr.score(X_train, y_train))from sklearn.metrics import classification_report
y_true, y_pred = y_test, lr.predict(X_test)print(classification_report(y_true, y_pred))技术支持
Logistic Regression score for training set:0.752932
precision recall f1-score support
False0.780.740.76179True0.690.740.71141
avg / total 0.740.740.74320技术支持
开箱即用的逻辑回归就优于 K-NN(无论是否缩放)。现在让我们对数据进行缩放并再次进行逻辑回归:
from sklearn.preprocessing import scale
Xs = scale(X)
Xs_train, Xs_test, y_train, y_test = train_test_split(Xs, y, test_size=0.2, random_state=42)
lr_2 = lr.fit(Xs_train, y_train)print('Scaled Logistic Regression score for test set: %f'% lr_2.score(Xs_test, y_test))
y_true, y_pred = y_test, lr_2.predict(Xs_test)print(classification_report(y_true, y_pred))技术支持
Scaled Logistic Regression score for test set:0.740625
precision recall f1-score support
False0.790.740.76179True0.690.740.72141
avg / total 0.740.740.74320技术支持
这很有意思!对逻辑回归而言,数据缩放并未带来性能提升。为什么会这样,尤其是此前我们看到 k 近邻在缩放后性能显著提升?原因在于:如果存在取值范围很大但对目标变量影响不大的预测变量,回归算法会将相应系数 \(a_i\) 调小,从而减弱其对预测的影响。k 近邻并没有这样的内置机制,因此我们非常需要对数据进行缩放。
# Set sc = True to scale your features
sc = False
# Load data
df = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv ' , sep = ';')
X = df.drop('quality' , 1).values # drop target variable
# Here we scale, if desired
if sc == True:
X = scale(X)
# Target value
y1 = df['quality'].values # original target variable
y = y1 <= 5 # new target variable: is the rating <= 5?
# Split the data into a test set and a training set X_train, X_test, y_train, y_test =
train_test_split(X, y, test_size=0.2, random_state=42)
# Train logistic regression model and print performance on the test set
lr = linear_model.LogisticRegression()
lr = lr.fit(X_train, y_train)
print('Logistic Regression score for training set: %f' % lr.score(X_train, y_train))
y_true, y_pred = y_test, lr.predict(X_test)
print(classification_report(y_true, y_pred))
在本系列的第一篇文章中,我探讨了预处理在机器学习(ML)分类任务中的作用,并深入剖析了 k 近邻算法(k-NN)和葡萄酒质量数据集。您会看到,对数值数据进行中心化和缩放能提升 k-NN 在若干模型评估指标(如准确率)上的表现。您也会看到,预处理并非孤立进行,其价值只能在面向预测的 ML 流水线语境中加以评估。不过,上文仅在单一模型 k-NN 的语境下讨论了预处理的重要性。那时我们的模型表现显著提升,但是否总是如此?并不一定!本文将考察在另一个基础模型——逻辑回归——中,对数值数据进行缩放与中心化的作用。您可以回看上一篇和/或文末的术语表来温习要点。我们仍将使用葡萄酒质量数据集。文中所有示例均使用 Python。如果您尚不熟悉 Python,可在此查看我们的数据科学课程。我将使用 pandas 满足数据框需求,并使用 scikit-learn 完成机器学习相关工作。
我将先简要介绍回归,它既可用于预测数值变量,也可用于预测类别。随后介绍线性回归与逻辑回归,并使用后者来预测红酒品质。接着我们将检验在回归设置下,中心化与缩放是否能帮助模型。
Python 回归简明介绍
Python 中的线性回归
如上所述,回归通常用于根据一个数值变量来预测另一个数值变量。例如,下面我们对波士顿房价数据(scikit-learn 内置数据集)进行线性回归:此处自变量(x 轴)为房间数量,因变量(y 轴)为价格。
这样的回归如何运作?简而言之,机制如下:我们希望将模型 \(y = ax + b\) 拟合到数据 \((x_i,y_i)\),也就是在给定数据的情况下,找到最优的 \(a\) 和 \(b\)。在最常见的普通最小二乘(OLS)表述中,假设误差发生在因变量上。因此,通过最小化 \[SSE = \sum_i (y_i - (ax_i + b))^2\] 来求得最优的 \(a\) 和 \(b\),而这一优化通常借助名为梯度下降的算法实现。下面我们对波士顿房价数据做一个简单线性回归:
该回归刻画了数据整体的递增趋势,但并不深入。我们只使用了一个预测变量,其实可以使用更多;那样模型中将有 \(n\) 个系数 \(a_1,\ldots,a_n\),每个预测变量对应一个系数。值得注意的是,系数 \(a_i\) 的大小表明相应变量与目标变量的相关强度。
Python 中的逻辑回归
回归也可用于分类问题。其首个自然示例便是逻辑回归。在二分类(两个标签)中,我们可将标签视作 0 与 1。仍以 \(x\) 表示预测变量,逻辑回归模型由逻辑函数给出:\[F(x) = \frac{1}{1+e^{-(ax+b)}}.\] 这是一条 S 形曲线,下面给出一个示例。对任意 \(x\),若 \(F(x) <0.5\),则逻辑模型预测 y = 0;反之若 \(F(X) > 0.5\),模型预测 \(y = 1\)。同样地,若我们有多个预测变量,则有 \(n\) 个系数 \(a_1,\ldots,a_n\),每个预测变量对应一个系数。在这种情况下,系数 \(a_i\) 的大小表明相应变量对预测结果的影响强度。
逻辑回归与数据缩放:葡萄酒数据集
既然我们已了解逻辑回归的机制,那就把它应用到可口的葡萄酒数据集上吧。我先导入数据,并绘制目标变量(好酒/差酒)作为回顾:
现在让我们运行逻辑回归,看看表现如何!
开箱即用的逻辑回归就优于 K-NN(无论是否缩放)。现在让我们对数据进行缩放并再次进行逻辑回归:
这很有意思!对逻辑回归而言,数据缩放并未带来性能提升。为什么会这样,尤其是此前我们看到 k 近邻在缩放后性能显著提升?原因在于:如果存在取值范围很大但对目标变量影响不大的预测变量,回归算法会将相应系数 \(a_i\) 调小,从而减弱其对预测的影响。k 近邻并没有这样的内置机制,因此我们非常需要对数据进行缩放。
在下一篇文章中,我将通过合成数据集、加入噪声,并考察随着噪声强度变化,中心化与缩放如何改变两种模型的表现,以此来解析 k-NN 与逻辑回归在中心化与缩放上的巨大差异。
在下面的交互窗口中,您可以自己动手尝试。若需要,您可以通过设置 sc = True 来对数据进行缩放。然后运行整个脚本,以得到逻辑回归模型的准确率及分类报告。
术语表
监督学习:从预测变量中推断目标变量的任务。例如,从“年龄”“性别”“是否吸烟”等预测变量推断目标变量“是否患有心脏病”。
分类任务:若目标变量由类别构成(如“点击”或“未点击”、“恶性”或“良性”肿瘤),则该监督学习任务为分类任务。
回归任务:若目标变量为连续变化的变量(如房价)或有序的类别变量(如“葡萄酒质量评分”),则该监督学习任务为回归任务。
k 近邻:一种用于分类任务的算法,将数据点赋予其 k 个最近邻居的多数表决所得的标签。
预处理:数据科学家为使数据更适合后续用途而进行的各种操作。例如,在对推特数据进行情感分析前,您可能需要去除任何 html 标签、空白字符、展开缩写,并将推文切分为其所含词语的列表。
中心化与缩放:二者均为对数值数据的预处理形式,即由数字构成的数据(相对例如类别或字符串);中心化是指用变量的均值去减每个数据点,使新变量的均值为 0;缩放是指将每个数据点乘以某个常数以改变数据范围。请参见正文了解其重要性与示例。
本文由 Jupyter 笔记本生成。您可在此处下载该笔记本。