6.标签特征二元化
处理分类变量还有另一种方法,不需要通过OneHotEncoder,我们可以用LabelBinarizer。
这是一个阈值与分类变量组合的方法。
In [1]:
from sklearn import datasets as d
iris = d.load_iris()
target = iris.target
How to do it...
导入LabelBinarizer()创建一个对象:
In [2]:
from sklearn.preprocessing import LabelBinarizer
label_binarizer = LabelBinarizer()
现在,将因变量的值转换成一个新的特征向量:
In [3]:
new_target = label_binarizer.fit_transform(target)
让我们看看new_target和label_binarizer对象的结果:
In [4]:
new_target.shape
Out[4]:
(150, 3)
In [5]:
new_target[:5]
In [6]:
new_target[-5:]
In [9]:
label_binarizer.classes_
Out[9]:
array([0, 1, 2])
iris的因变量基数为3,就是说有三种值,
当LabelBinarizer将 N×1N×1 向量转换成 N×CN×C 矩阵时, CC 就是 N×1N×1 向量的基数。
需要注意的是,当label_binarizer处理因变量之后,再转换基数以外的值都是[0,0,0]:
In [15]:
label_binarizer.transform([4])
Out[15]:
array([[0, 0, 0]])
There's more...
0和1并不一定都是表示因变量中的阳性和阴性实例。例如,如果我们需要用1000表示阳性值,用-1000表示阴性值,我们可以用label_binarizer处理:
In [22]:
label_binarizer = LabelBinarizer(neg_label=-1000, pos_label=1000)
label_binarizer.fit_transform(target)[:5]
scikit-learn有一些常见的计算方法,它可以对现有数据进行变换填补NA值。
import numpy as np
iris = datasets.load_iris()
iris_X = iris.data
masking_array = np.random.binomial(1, .25, iris_X.shape).astype(bool)
iris_X[masking_array] = np.nan
masking_array[:5]
In [4]:
iris_X[:5]
impute = preprocessing.Imputer()
iris_X_prime = impute.fit_transform(iris_X)
iris_X_prime[:5]
均值mean(默认方法)
中位数median
众数most_frequent
scikit-learn会用指定的方法计算数据集中的每个缺失值,然后把它们填充好。
例如,用median方法重新计算iris_X,重新初始化impute即可:
In [9]:
impute = preprocessing.Imputer(strategy='median')
iris_X_prime = impute.fit_transform(iris_X)
iris_X_prime[:5]
iris_X[:5]
In [11]:
impute = preprocessing.Imputer(missing_values=-1)
iris_X_prime = impute.fit_transform(iris_X)
iris_X_prime[:5]
Out[11]:
array([[ 5.1 , 3.05221239, 1.4 , 0.2 ],
[ 4.9 , 3.05221239, 1.4 , 0.2 ],
[ 4.7 , 3.2 , 1.3 , 0.2 ],
[ 5.86306306, 3.1 , 1.5 , 1.21388889],
[ 5. , 3.6 , 3.82685185, 0.2 ]])
There's more...
pandas库也可以处理缺失值,而且更加灵活,但是重用性较弱:
In [12]:
import pandas as pd
iris_X[masking_array] = np.nan
iris_df = pd.DataFrame(iris_X, columns=iris.feature_names)
iris_df.fillna(iris_df.mean())['sepal length (cm)'].head(5)
Out[12]:
0 5.100000
1 4.900000
2 4.700000
3 5.863063
4 5.000000
Name: sepal length (cm), dtype: float64
其灵活性在于,fillna可以填充任意统计参数值:
In [13]:
iris_df.fillna(iris_df.max())['sepal length (cm)'].head(5)
管线命令可以把多个步骤组合成一个对象执行。
import numpy as np
mat = datasets.make_spd_matrix(10)
masking_array = np.random.binomial(1, .1, mat.shape).astype(bool)
mat[masking_array] = np.nan
mat[:4, :4]
In [2]:
from sklearn import preprocessing
impute = preprocessing.Imputer()
scaler = preprocessing.StandardScaler()
mat_imputed = impute.fit_transform(mat)
mat_imputed[:4, :4]
In [5]:
mat_imp_and_scaled = scaler.fit_transform(mat_imputed)
mat_imp_and_scaled[:4, :4]
现在我们用pipeline来演示:
In [6]:
from sklearn import pipeline
pipe = pipeline.Pipeline([('impute', impute), ('scaler', scaler)])
我们看看pipe的内容。和前面介绍一致,管线命令定义了处理步骤:
In [7]:
pipe
Out[7]:
Pipeline(steps=[('impute', Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)),
然后在调用pipe的fit_transform方法,就可以把多个步骤组合成一个对象了:
In [10]:
new_mat = pipe.fit_transform(mat)
new_mat[:4, :4]
In [11]:
np.array_equal(new_mat, mat_imp_and_scaled)
Out[11]:
True
pipeline最重要的函数也不外乎下面三个:
fit
transform
fit_transform
具体来说,如果管线命令有N个对象,前N-1个对象必须实现fit和transform,
首先是方便。
其次,就是使用交叉验证。模型可以变得很复杂。如果管线命令中的一个步骤调整了参数,
主成分分析(Principal component analysis,PCA)是本书介绍的第一个高级技术。
PCA是scikit-learn的一个分解模块。
In [1]:
from sklearn import datasets
iris = datasets.load_iris()
iris_X = iris.data
In [2]:
from sklearn import decomposition
然后,初始化一个PCA对象:
In [3]:
pca = decomposition.PCA()
pca
Out[3]:
PCA(copy=True, n_components=None, whiten=False)
PCA的参数很少。这样PCA对象就创建了,
In [6]:
iris_pca = pca.fit_transform(iris_X)
iris_pca[:5]
这样PCA就完成了,我们可以看看降维的效果:
In [8]:
pca.explained_variance_ratio_
Out[8]:
array([ 0.92461621, 0.05301557, 0.01718514, 0.00518309])
PCA用正交向量集表示原始数据集。
PCA将原始数据集映射到新的空间中,里面每个列向量都是彼此正交的。从数据分析的视角看,
数据分析里面维度多会导致维度灾难,因此降维至关重要。通常算法处理高维训练集时会出现拟合过度(overfit)
为了演示这点,我们用PCA将iris数据集转换成二维数据。iris数据集用全部的维度通常可以很好的分类:
In [9]:
pca = decomposition.PCA(n_components=2)
iris_X_prime = pca.fit_transform(iris_X)
iris_X_prime.shape
Out[9]:
(150, 2)
我们的矩阵现在是 150×2150×2 ,不是 150×4150×4 了。二维变量更容易可视化:
PCA对象还可以一开始设置解释变量的比例。例如,如果我们想介绍98%的变量,PCA对象就可以这样创建:
In [15]:
pca = decomposition.PCA(n_components=.98)
iris_X_prime = pca.fit_transform(iris_X)
pca.explained_variance_ratio_.sum()
Out[15]:
0.99481691454981014
In [16]:
iris_X_prime.shape
Out[16]:
(150, 3)
因子分析(factor analysis)是另一种降维方法。与PCA不同的是,因子分析有假设而PCA没有假设。
这个主题将浓缩(boil down)样本数据集的显性特征,尝试像理解因变量一样地理解自变量之间的隐藏特征。
让我们再用iris数据集来比较PCA与因子分析,首先加载因子分析类:
In [3]:
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.decomposition import FactorAnalysis
In [6]:
fa = FactorAnalysis(n_components=2)
iris_two_dim = fa.fit_transform(iris.data)
iris_two_dim[:5]
由于因子分析是一种概率性的转换方法,我们可以通过不同的角度来观察,
因子分析也有不足之处。由于你不是通过拟合模型直接预测结果,拟合模型只是一个中间步骤。
因子分析与前面介绍的PCA类似。但两者有一个不同之处。PCA是通过对数据进行线性变换获取一个能够解释
而因子分析的基本假设是,有 MM 个重要特征和它们的线性组合(加噪声),能够构成原始的 NN 维数据集。
用于分类的分解方法——字典学习(Dictionary Learning),将数据集转换成一个稀疏的形式。
DictionaryLearning方法的思想是把特征看作构成数据集的基础。首先我们导入iris数据集:
In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
In [2]:
from sklearn.datasets import load_iris
iris = load_iris()
iris_data = iris.data
iris_target = iris.target
首先,导入DictionaryLearning:
In [3]:
from sklearn.decomposition import DictionaryLearning
然后用三个成分表示iris数据集中花的类型:
In [4]:
dl = DictionaryLearning(3)
再用fit_transform转换其他数据,这样我们就可以对比训练前后的数据了:
In [5]:
transformed = dl.fit_transform(iris_data[::2])
transformed[:5]
意,每个成分的值分别平行 xx , yy 和 zz 三个轴,其他坐标都是0;这就是稀疏性。
In [6]:
from mpl_toolkits.mplot3d import Axes3D
colors = np.array(list('rgb'))
f = plt.figure()
ax = f.add_subplot(111, projection='3d')
ax.set_title("Training Set")
ax.scatter(transformed[:, 0], transformed[:, 1], transformed[:, 2], color=colors[iris.target[::2]]);
下面,让我们用fit而不用fit_transform来训练数据集:
In [7]:
transformed = dl.transform(iris_data[1::2])
In [8]:
colors = np.array(list('rgb'))
f = plt.figure()
ax = f.add_subplot(111, projection='3d')
ax.set_title("Training Set")
ax.scatter(transformed[:, 0], transformed[:, 1], transformed[:, 2], color=colors[iris.target[1::2]]);
随机梯度下降法(Stochastic Gradient Descent,SGD),我们将用它解决回归问题,后面我们还用它处理分类问题。
SGD成为许多机器学习算法的核心的另一个原因是它很容易描述过程。我们对数据作一些变换,
from sklearn import datasets
X, y = datasets.make_regression(int(1e6))
print("{:,}".format(int(1e6)))
1,000,000
还在我们用的是NumPy数组,所以我们可以获得nbytes。
In [9]:
print("{:,}".format(X.nbytes))
800,000,000
In [10]:
X.nbytes / 1e6
Out[10]:
800.0
In [11]:
X.nbytes / (X.shape[0] * X.shape[1])
Out[11]:
8.0
现在,我们有了数据,就用SGDRegressor来拟合:
In [13]:
import numpy as np
from sklearn import linear_model
sgd = linear_model.SGDRegressor()
train = np.random.choice([True, False], size=len(y), p=[.75, .25])
sgd.fit(X[train], y[train])
Out[13]:
SGDRegressor(alpha=0.0001, average=False, epsilon=0.1, eta0=0.01,
fit_intercept=True, l1_ratio=0.15, learning_rate='invscaling',
loss='squared_loss', n_iter=5, penalty='l2', power_t=0.25,
random_state=None, shuffle=True, verbose=0, warm_start=False)
损失函数是squared_loss,与线性回归里的残差平方和是一样的。
In [16]:
linear_preds = sgd.predict(X[~train])
In [17]:
%matplotlib inline
from matplotlib import pyplot as plt
f, ax = plt.subplots(figsize=(7, 5))
f.tight_layout()
ax.hist(linear_preds - y[~train],label='Residuals Linear', color='b', alpha=.5);
ax.set_title("Residuals")
ax.legend(loc='best');
标准的梯度下降法的思想是在每次迭代计算一个新的相关系数矩阵,然后用学习速率(learning rate)和