天天看點

sklearn 使用以及資料集拆分與特征預處理

莺尾花預測是KNN一個經典的例子, 可以了解為一個分類預測。莺尾花的資料集有150 條,每個樣本包含:

特征值四:花瓣花萼的長度和寬度

目标值有3種:setosa、versicolor、virginica

1. sklearn 資料集介紹

其擷取資料集有兩種方式:

load_xxx: 擷取小資料集(依賴庫自帶)
fetch_xxx: 從網際網路下載下傳一些大的資料集      

以莺尾花資料集為例子:

from sklearn.datasets import load_iris
# 擷取鸢尾花資料集
iris = load_iris()
print("鸢尾花資料集的傳回值:\n", iris)
# 傳回值是一個繼承自字典的Bench
print("鸢尾花的特征值:\n", iris["data"])
print("鸢尾花的目标值:\n", iris.target)
print("鸢尾花特征的名字:\n", iris.feature_names)
print("鸢尾花目标值的名字:\n", iris.target_names)
print("鸢尾花的描述:\n", iris.DESCR)      

結果:

鸢尾花資料集的傳回值:
 {'data': array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2], ...
鸢尾花的特征值:
 [[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2] ...
鸢尾花的目标值:
 [0 0 0 0 0 ...
鸢尾花特征的名字:
 ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
鸢尾花目标值的名字:
 ['setosa' 'versicolor' 'virginica']
鸢尾花的描述:
 .. _iris_dataset:
 ...      

2. 莺尾花資料可視化

# 内嵌繪圖
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris
# 擷取鸢尾花資料集
iris = load_iris()
# 把資料轉換成dataframe的格式
iris_d = pd.DataFrame(iris['data'], columns = ['Sepal_Length', 'Sepal_Width', 'Petal_Length', 'Petal_Width'])
iris_d['Species'] = iris.target

def plot_iris(iris, col1, col2):
    sns.lmplot(x = col1, y = col2, data = iris, hue = "Species", fit_reg = False)
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.title('iris graph')
    plt.show()
plot_iris(iris_d, 'Petal_Width', 'Sepal_Length')      

結果:

sklearn 使用以及資料集拆分與特征預處理

3. 資料集拆分

方法:

def train_test_split(
    *arrays,
    test_size=None,
    train_size=None,
    random_state=None,
    shuffle=True,
    stratify=None,
):
    """Split arrays or matrices into random train and test subsets.

    Quick utility that wraps input validation and
    ``next(ShuffleSplit().split(X, y))`` and application to input data
    into a single call for splitting (and optionally subsampling) data in a
    oneliner.

    Read more in the :ref:`User Guide <cross_validation>`.

    Parameters
    ----------
    *arrays : sequence of indexables with same length / shape[0]
        Allowed inputs are lists, numpy arrays, scipy-sparse
        matrices or pandas dataframes.

    test_size : float or int, default=None
        If float, should be between 0.0 and 1.0 and represent the proportion
        of the dataset to include in the test split. If int, represents the
        absolute number of test samples. If None, the value is set to the
        complement of the train size. If ``train_size`` is also None, it will
        be set to 0.25.

    train_size : float or int, default=None
        If float, should be between 0.0 and 1.0 and represent the
        proportion of the dataset to include in the train split. If
        int, represents the absolute number of train samples. If None,
        the value is automatically set to the complement of the test size.

    random_state : int, RandomState instance or None, default=None
        Controls the shuffling applied to the data before applying the split.
        Pass an int for reproducible output across multiple function calls.
        See :term:`Glossary <random_state>`.

    shuffle : bool, default=True
        Whether or not to shuffle the data before splitting. If shuffle=False
        then stratify must be None.

    stratify : array-like, default=None
        If not None, data is split in a stratified fashion, using this as
        the class labels.
        Read more in the :ref:`User Guide <stratification>`.

    Returns
    -------
    splitting : list, length=2 * len(arrays)
        List containing train-test split of inputs.

        .. versionadded:: 0.16
            If the input is sparse, the output will be a
            ``scipy.sparse.csr_matrix``. Else, output type is the same as the
            input type.      

測試:預設是 訓練:測試=3:1, 也就是訓練=0.75

# 内嵌繪圖
from sklearn.datasets import load_iris

# 1、擷取鸢尾花資料集
from sklearn.model_selection import train_test_split

iris = load_iris()
# 對鸢尾花資料集進行分割
# 訓練集的特征值x_train 測試集的特征值x_test 訓練集的目标值y_train 測試集的目标值y_test
# random_state: 随機數種子,不同的種子會造成不同的随機采樣結果。相同的種子采樣結果相同
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
print("x_train:\n", x_train.shape)
print("x_train:\n", x_train)
print("x_test:\n", x_test)
print("y_train:\n", y_train)
print("y_test:\n", y_test)      

4. 特征預處理

1. 什麼是特征預處理

簡單說:通過一些轉換函數将特征資料轉換成更加适合算法模型的特征資料的過程。包含歸一化和标準化。

sklearn 使用以及資料集拆分與特征預處理

2. 為什麼需要進行歸一化/标準化?

特征的機關或者大小差異較大,或者某特征的方差相比其他的特征要大出幾個數量級,容易影響支配目标結果,使得一些算法無法學習到其他的特征。

同樣以上面的資料為例子,特征1和特征2的資料量相差比較大,但是我們認為其重要程度是一樣的,是以我們需要将其進行歸一化與标準化。

3. 歸一化

通過對原始資料進行變換把資料映射到(預設為[0,1])之間

sklearn 使用以及資料集拆分與特征預處理
作用于每一列,max為一列的最大值,min為一列的最小值,那麼X’’為最終結果,mx,mi分别為指定區間值預設mx為1,mi為0
sklearn 使用以及資料集拆分與特征預處理
import numpy as np
from sklearn.preprocessing import MinMaxScaler

# 1. 構造資料
x = np.array([[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]])
print(x)
transfer = MinMaxScaler(feature_range=(0, 1))
# 2. 調用fit_transform
data = transfer.fit_transform(x)
print("最小值最大值歸一化處理的結果:\n", data)      

結果:

[[90  2 10 40]
 [60  4 15 45]
 [75  3 13 46]]
最小值最大值歸一化處理的結果:
 [[1.         0.         0.         0.        ]
 [0.         1.         1.         0.83333333]
 [0.5        0.5        0.6        1.        ]]      

最大值最小值是變化的,另外,最大值與最小值非常容易受異常點(資料特别大或者特别小)影響,是以這種方法魯棒性較差,隻适合傳統精确小資料場景。

4. 标準化

通過對原始資料進行變換把資料變換到均值為0,标準差為1範圍内。在已有樣本足夠多的情況下比較穩定,适合現代嘈雜大資料場景。

sklearn 使用以及資料集拆分與特征預處理
作用于每一列,mean為平均值,σ為标準差
import numpy as np
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# 1. 構造資料
x = np.array([[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]])
print(x)
transfer = StandardScaler()
# 2. 調用fit_transform
data = transfer.fit_transform(x)
print("标準化的結果:\n", data)
print("每一列特征的平均值:\n", transfer.mean_)
print("每一列特征的方差:\n", transfer.var_)      

結果:

[[90  2 10 40]
 [60  4 15 45]
 [75  3 13 46]]
标準化的結果:
 [[ 1.22474487 -1.22474487 -1.29777137 -1.3970014 ]
 [-1.22474487  1.22474487  1.13554995  0.50800051]
 [ 0.          0.          0.16222142  0.88900089]]
每一列特征的平均值:
 [75.          3.         12.66666667 43.66666667]
每一列特征的方差:
 [150.           0.66666667   4.22222222   6.88888889]