avatar


5.scikit-learn的拾遗

在之前的特征工程部分,我们已经用了scikit-learn,后面讲具体算法的时候,还会继续用scikit-learn。这一部分,主要讨论一下前面没讲,后面也不会专门讲的,但是又和scikit-learn相关的部分。

我们称之为《"scikit-learn"的拾遗》。
主要内容有:

  1. scikit-learn的数据集
  2. 转换器
  3. 估计器

scikit-learn的数据集

这一部分的内容有

  1. 数据集的划分
  2. 数据集的接口
  3. 数据集的举例

数据集的划分

首先,我们肯定不能把拿到的所有数据都用来训练模型。否则的话,我们怎么知道我们模型的好坏呢?
我们需要把数据进行划分为训练集和测试集。
一般情况下,是75%的训练数据,25%的测试数据。至于为什么是75% - 25%,这是一个经验公式。

  • 训练数据用于训练,构建模型。
  • 测试数据用于模型检验。

特别注意:

  1. 我们在划分数据集的时候,不能简单的前75%作为训练集,后25%作为测试数据。因为有些情况下,数据会根据目标值进行排序。我们直接选取75%,可能会导致用于训练的数据,绝大部分目标值都是一样的。
    通常建议,随机抽取。
  2. 对于时间序列问题,需要注意的是,一定不能有数据泄漏。

对数据的划分也很简单。

1
from sklearn.model_selection import train_test_split

数据集的接口

sklearn.datasets
如图所示,在scikit-learn中有两种数据集接口,分别是load开头的,和fetch开头的。

  • 以load开头的,用以获取小规模数据集。这些数据集已经在datasets中,不需要通过网络下载。
  • 以fetch开头的,用以获取大规模数据集。这些数据集不在datasets中,需要通过网络下载。

无论是laod或者fetch,所拿到数据的格式都是都是一样的,sklearn.datasets.base.Bunch(字典格式)。
内容有

  • data,特征数据数组。是[样本数 * 特征数]的二维np.ndarry数组。
    • 一行代表一个样本,一列代表一个特征。
  • target,目标数组。是样本数的一维np.ndarry数组。
  • DESCR,数据描述
  • feature_names,特征名。
    • 注意:不是所有的数据都有这些特征名。比如新闻数据没有。
  • target_names,目标名。
    • 注意:不是所有的数据都有目标名。

数据集的举例

我们举两个例子,分别是数据集的获取和数据集的分割。

数据集的获取

我们以对小数据集的获取和大数据集的获取分别举例。

小数据集的获取

我们以鸢尾花为例。

很多机器学习的教程,尤其是在讲kNN算法的时候,都喜欢以鸢尾花为例子。所以,我想,绝大部分机器学习算法工程师,大概都知道世界上有一种花叫做"鸢尾花"。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from sklearn.datasets import load_iris
li = load_iris()
# 获取特征值
print('-' * 10)
print(li.data)
# 获取目标值
print('-' * 10)
print(li.target)
# 获取特征名
print('-' * 10)
print(li.feature_names)
# 获取目标名
print('-' * 10)
print(li.target_names)
# 获取描述
print('-' * 10)
print(li.DESCR)

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
----------
[[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]
[4.7 3.2 1.3 0.2]
[4.6 3.1 1.5 0.2]
[5. 3.6 1.4 0.2]

【部分运行结果略】

----------
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
----------
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
----------
['setosa' 'versicolor' 'virginica']
----------
.. _iris_dataset:

Iris plants dataset
--------------------

**Data Set Characteristics:**

:Number of Instances: 150 (50 in each of three classes)
:Number of Attributes: 4 numeric, predictive attributes and the class
:Attribute Information:
- sepal length in cm

【部分运行结果略】

大数据集的获取

我们以20newsgroups为例。

1
from sklearn.datasets import fetch_20newsgroups

该方法的需要注意这些:

  • 参数data_home
    • 默认值会是当前用户home目录下的scikit_learn_data
    • 如果填了内容,则不采用默认值。
      • 例如:填data,会是当前Python项目home目录下的data
  • 参数subset,可选traintestall

注意,该方法可能会报SSL的证书错误,解决方法为添加如下的代码,忽略证书。

1
2
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

该数据集就是没有feature_names的例子。
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sklearn.datasets import fetch_20newsgroups
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
news = fetch_20newsgroups(data_home='Desktop',subset='all')
# 获取特征值
print('-' * 10)
print(news.data)
# 获取目标值
print('-' * 10)
print(news.target)
# 获取目标名
print('-' * 10)
print(news.target_names)
# 获取描述
print('-' * 10)
print(news.DESCR)

运行结果略

除此之外,我们再介绍一个方法。

1
datasets.clear_data_home(data_home=None)
清除目录下的数据

数据集的分割

1
from sklearn.model_selection import train_test_split

该方法的需要注意这些:

  • 入参
    • x 数据集的特征值
    • y 数据集的标签纸
    • test_size 测试集的占比,为float类型的小数
    • random_state 随机数的种子
  • 返回
    • 对于返回值,顺序固定,我们在接收返回的时候,一定要注意顺序。顺序是
      1. 训练集的特征
      2. 测试集的特征
      3. 训练集的目标
      4. 测试集的目标

伪代码:

1
训练集的特征,测试集的特征,训练集的目标,测试集的目标 = train_test_split(数据集的特征,数据集的目标,测试集的占比=0.25)

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
li = load_iris()
# 注意返回值
# x_train,x_test,y_train,y_test 的位置
x_train,x_test,y_train,y_test = train_test_split(li.data,li.target,test_size=0.25)
print('-' * 10)
print(x_train)
print('-' * 10)
print(x_test)
print('-' * 10)
print(y_train)
print('-' * 10)
print(y_test)

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
----------
[[5.4 3.9 1.7 0.4]
[5.5 2.4 3.8 1.1]
[6.7 3.1 4.7 1.5]
[7.7 2.6 6.9 2.3]
[5.1 3.8 1.5 0.3]

【部分运行结果略】

----------
[[4.9 3.1 1.5 0.2]
[7.1 3. 5.9 2.1]
[6.9 3.2 5.7 2.3]
[6.4 3.2 5.3 2.3]
[5.1 3.8 1.6 0.2]

【部分运行结果略】

----------
[0 1 1 2 0 1 2 2 0 0 1 0 1 0 2 1 2 0 2 1 2 2 2 1 2 0 2 2 1 2 1 1 0 1 1 0 0
1 1 2 2 2 1 0 2 1 0 2 0 1 0 1 1 2 2 0 0 1 2 2 1 1 1 1 2 2 0 1 2 1 1 2 1 2
0 0 1 0 2 1 1 1 1 1 0 0 1 0 2 0 2 2 2 0 0 1 0 2 1 2 0 0 1 0 2 0 0 1 1 1 1
1]

【部分运行结果略】

[0 2 2 2 0 2 0 2 0 0 0 0 0 0 2 2 1 2 0 1 0 2 1 0 0 1 2 2 0 2 0 0 1 2 2 2 1
0]

转换器

首先,我们回顾一下我们在特征工程时候的步骤。
示例代码:

1
2
3
4
5
from sklearn.feature_extraction import DictVectorizer
dict = DictVectorizer(sparse=False)
data = [{'city': '上海', 'temperature': 22,'weather':'雨'}, {'city': '南昌', 'temperature': 24,'weather':'阴'}]
print(dict.fit_transform(data))
print(dict.get_feature_names())

我们的操作是

  1. 实例化一个转换器类
  2. 调用fit_transform方法

通过这个步骤,我们把数据集进行转换
我们还有两个方法。

  1. fit
  2. transform

fit_transform = fit + transform
示例代码:

1
2
3
4
5
6
7
8
from  sklearn.feature_selection import VarianceThreshold
X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
print(X)
selector = VarianceThreshold()
print(selector.fit_transform(X))
print('-' * 10)
print(selector.fit(X))
print(selector.transform(X))

运行结果:

1
2
3
4
5
6
7
8
9
[[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
[[2 0]
[1 4]
[1 1]]
----------
VarianceThreshold(threshold=0.0)
[[2 0]
[1 4]
[1 1]]
  • fit的操作是输入数据,同时会计算平均值、方差或者词的列表。
  • transform的操作是对数据进行转换。

所以,我们一般用fit_transform,而不是先用fit再用transform

除非,我们有特殊需求。

示例代码:

1
2
3
4
5
6
7
8
9
10
from  sklearn.feature_selection import VarianceThreshold
X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
print(X)
Y = [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
print(Y)
selector = VarianceThreshold()
print(selector.fit_transform(X))
print('-' * 10)
print(selector.fit(X))
print(selector.transform(Y))

运行结果:

1
2
3
4
5
6
7
8
9
10
[[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[2 0]
[1 4]
[1 1]]
----------
VarianceThreshold(threshold=0.0)
[[1 2]
[2 3]
[3 4]]

如代码所示
如果我们根据一组数据来生成一个转换器,并用这个转换器来转换另一组数据。
那么,就只能先用fit,再用transform了。

估计器

scikit-learn中,估计器非常重要,是实现算法的API。
例如:

  1. 用于分类的估计器

    • sklearn.neighbors (kNN算法)
    • sklearn.naive_bayes (朴素贝叶斯)
    • sklearn.linear_model.LogisticRegression (逻辑回归)
    • sklearn.tree (决策树与随机森林)
  2. 用于回归的估计器

    • sklearn.linear_model.LogisticRegression (线性回归)
    • sklearn.linear_model.Ridge (岭回归)

估计器的用法,和上述的转换器类似。

  1. 调用fit
    1
    fit(x_train,y_train)
  2. 调用predict或者score
    1
    2
    y_predict = predict(x_test)
    score(x_test,y_test)
文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/10205
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

评论区