小白入门sklearn机器学习之——入门机器学习并不难

发布时间:2023-04-01 11:00

文章目录

    • 摘要
    • 1.scikit-learn是什么
    • 2.API的类型:
    • 3.API使用的基本套路
      • 3.1 转换器`.fit + .transform` 和 `.fit_transform`的区别
      • 3.2 转换器的使用套路
      • 3.3 估计器的使用套路
    • 4.数据的预处理
      • 4.1 归一化
      • 4.2 标准化
    • 5.数据的特征提取
      • 5.1 字典数据的提取
      • 5.2文本数据的提取
    • 总结

更新日期 更新次数 更新章节
2020-03-19 第1次更新 1.0
2020-04-12 第2次更新 1.0-5.0

摘要

本文不涉及公式推导,从纯代码的角度告诉你如何入门使用scikit-learn包。适合非计算机专业的小白0基础体验机器学习,帮助大家消除“公式恐惧症”。

1.scikit-learn是什么

sklearn包是一个pyton的机器学习包,基于numpy和scipy建立,遵守BSD许可(这个许可的开放度最高,程序员可以为所欲为,包括运用于商业软件)。
sklearn的官网在这里

2.API的类型:

  1. 预处理(preprocessing)
  2. 模型选择(model selection)
  3. 分类(classification)
  4. 回归(regression)
  5. 降维(dimensionality reduction)
  6. 聚类(clustering)

3.API使用的基本套路

scikit-learn的api中涉及到的类绝大多数都有 obj.fit(),或者obj.fit_transform 方法,这两种方法的专业名词叫估计器(.fit)和转换器(.fit+.transform 或者 .fit_transform)

3.1 转换器.fit + .transform.fit_transform的区别

我们用一个实例来解释这个问题。

from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
data1= np.random.randint(3,size=(3,3))
data1
array([[0, 1, 1],
       [0, 0, 1],
       [1, 1, 1]])

然后我们使用.fit_transform的方法对data1进行归一化

s=MinMaxScaler()
result=s.fit_transform(data1)
result
array([[0., 1., 0.],
       [0., 0., 0.],
       [1., 1., 0.]])

然后我们使用.fit+.transform的方法再来一遍

>>s=MinMaxScaler()
>>result=s.fit(data1)
>>result=s.transform(data1)
result
array([[0., 1., 0.],
       [0., 0., 0.],
       [1., 1., 0.]])

结果是一样的,所以区别在哪里呢?我们看下面的例子:

>data2= np.random.randint(3,size=(3,3))
>data2
array([[1, 2, 2],
       [2, 2, 0],
       [2, 0, 1]])
       
>s=MinMaxScaler()
>result=s.fit(data2)
>result=s.transform(data2)

result
array([[0. , 1. , 1. ],
       [1. , 1. , 0. ],
       [1. , 0. , 0.5]])

>s=MinMaxScaler()
>result=s.fit(data2)
>result=s.transform(data1)

result
array([[-1. ,  0.5,  0.5],
       [-1. ,  0. ,  0.5],
       [ 0. ,  0.5,  0.5]])


.fit 是用来计算.transform所需要的数据,例如均值、方差等。上面的最后一个例子中,最后一段代码在对data1进行归一化的时候使用的是data2的min和max。

3.2 转换器的使用套路

总结一下转换器的使用套路,就三行

#第一步,实例化
object_name= class_name(param)

#第二步,拟合计算 .fit()
result=object_name.fit(data) 拟合数据,意思就是训练了
#第三步,转换.transform()
result=object_name.transform(data) 

#当然,如果计算和转换用的是同一个数据集,那么第二步和第三步也可以合并成
result=object_name.fit_transform(data) 

3.3 估计器的使用套路

我们用鸢尾花数据来做两个机器学习模型,分别是KNN、随机森林(先不考虑超参数的优化)


from sklearn import neighbors, datasets
from sklearn.ensemble import RandomForestClassifier
import numpy as np

n_neighbors = 11

# 导入数据
iris = datasets.load_iris()
x = iris.data[:, :2]  # 我们只采用前两个feature,方便画图在二维平面显示
y = iris.target

#上面数据准备好了,我们来拟合(训练)KNN
KNN_clf = neighbors.KNeighborsClassifier(n_neighbors)
KNN_clf.fit(x, y)

#然后我们来拟合(训练)随机森林
forest_clf = RandomForestClassifier(random_state=42)
forest_clf.fit()

#然后我们要预测的话。。
KNN_clf.predict(x, y)
forest_clf.predict(x, y)

综上所述,这个包是非常友好的,即便是你对机器学习算法完全不懂,也可以迅速拟合各种机器学习模型。所以,机器学习模型到底难在哪呢?是超参数的优化!是超参数的优化!是超参数的优化! 这是进阶学习的重点内容!当然,如果你想水非计算机专业的论文(比如交通、土木之类的),你也可以用暴力搜的方法。

但是事实上,sklearn提供了这种暴力搜超参数的机制。后续章节会有详细的说明。总结一下,训练机器学习模型的一般步骤,也就是估计器的使用方法。

#第一步,实例化
object_name= class_name(param)

#第二步,训练
object_name.fit(X, y) 拟合数据,意思就是训练了。

#第三步,预测
object_name.predict(x, y)

这种语法跟R语言很像,另外statsmodels 也是使用了这种语法。这种方法可以在我们在实际应用中专注于超参数的优化。

4.数据的预处理

这一节是对sklearn用户手册中6.3节的要点的整理。 用户手册中的6.3节介绍了sklearn.preprocessing模块。这个模块致力于将原始数据集中的各个特征向量(你可以理解成数据表格中的行、列),转化为更适合sklearn中各种算法的表示形式。主要包括了标准化,去中心化以及方差归一化

4.1 归一化

归一化就是把各列的数据限定在0~1之间,公式如下:

X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min

这样做的理由是,有些数据的特征scale非常小,如果不将他们统一到同一个尺度,scale大的特征将会占主导地位,归一化的假设就是:假设所有的特征同等重要!
注意:但是这种方法对离群点特别敏感,因为离群点会拉大数据特征的最大值和最小值,所以这个方法的用途并不广泛。它的使用方法可以参看3.1节

4.2 标准化

数据的标准化是所有的估计算法的共同要求,换句话说在使用sklearn的各种算法进行拟合之前,这一步是必须要做的。官方的解释是:假如一个变量是服从正态分布的,但如果不是标准正态分布(mean:0,sd:1)的话,他们的表现会很差。

实际应用中,不可能所有的变量都是服从正态分布的,但是我们可以用相似的方法将均值和方差进行处理。某一列数据逐个减去他们的方差,然后再除以标准差。类似于将正态分布转化为标准正态分布的方法。公式如下:

z = (x - u) / s

这么做的理由是,很多学习算法的目标函数都假设特征是标准化的,如果一个变量方差很大,它会支配整个计算结果,说白了就是其他变量的影响将会弱化,所以所有变量都在同一尺度上进行比较的话,就会得到更可靠的结果。

preprocessing模块提供了一个叫StandardScale的类,它能很轻易的完成数据的转换。

from sklearn import preprocessing
import numpy as np
#首先任意设置一个二维的数据,行代表观测,列代表变量
X_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])


scaler = preprocessing.StandardScaler().fit_transform(X_train)
print(scaler)
[[ 0.         -1.22474487  1.33630621]
 [ 1.22474487  0.         -0.26726124]
 [-1.22474487  1.22474487 -1.06904497]]
#当然你也可以按照下面的方法写:
scaler = preprocessing.StandardScaler() #实例化
scaler=scaler.fit_transform(X_train) #拟合
print(scaler)
[[ 0.         -1.22474487  1.33630621]
 [ 1.22474487  0.         -0.26726124]
 [-1.22474487  1.22474487 -1.06904497]]

5.数据的特征提取

这一节主要涉及字典数据的提取和文本数据的提取。api是sklearn.feature_extraction

5.1 字典数据的提取

字典数据提取的api是sklearn.feature_extraction.DictVectorizer

from sklearn.feature_extraction import DictVectorizer
import pandas as pd
import numpy as np

D=[{\'city\':\'北京\', \'temprature\': 34}, {\'city\':\'深圳\', \'temprature\': 27}, {\'city\':\'上海\', \'temprature\': 29}]
print(D)
[{\'city\': \'北京\', \'temprature\': 34}, {\'city\': \'深圳\', \'temprature\': 27}, {\'city\': \'上海\', \'temprature\': 29}]


dict=DictVectorizer(sparse=False,sort=True) #实例化
data=dict.fit_transform(D)
print(data)

[[ 0.  1.  0. 34.]
 [ 0.  0.  1. 27.]
 [ 1.  0.  0. 29.]]

#下面这个注意,只有实例里有get_feature_names
names=dict.get_feature_names()
print(names)
[\'city=上海\', \'city=北京\', \'city=深圳\', \'temprature\']


#如果想把数据转到字典状态
data_=dict.inverse_transform(data)
print(data_)
[{\'city=北京\': 1.0, \'temprature\': 34.0}, {\'city=深圳\': 1.0, \'temprature\': 27.0}, {\'city=上海\': 1.0, \'temprature\': 29.0}



#然后我们可以生成pandas的DataFrame
pd.DataFrame(columns=dict.get_feature_names(),data=data)

city=上海	city=北京	city=深圳	temprature
0	0.0	1.0	0.0	34.0
1	0.0	0.0	1.0	27.0
2	1.0	0.0	0.0	29.0

我们可以看到,特征提取之后,对于类别变量采用的是one-hot编码。类似于统计学里的哑变量(dummy)。意思是当这个样本是某一个类别的时候就是1,不是这个类别的时候就是0。一般来说,同一个变量大类的各个哑变量是互斥的。

这里注意一下dict=DictVectorizer(sparse=False,sort=True) #实例化这个语句,里面有一个参数叫sparse,这个参数等于True的时候是生成一个sparse矩阵,这个是scipy的标准数据格式之一。如果这个地方改成True看一下结果:

(0, 1)	1.0
(0, 3)	34.0
(1, 2)	1.0
(1, 3)	27.0
(2, 0)	1.0
(2, 3)	29.0

对比下面这个结果:

[[ 0.  1.  0. 34.]
 [ 0.  0.  1. 27.]
 [ 1.  0.  0. 29.]]

sparse矩阵的含义是:从第0行开始看,(0,1)的含义是第0行,第1列的这个元素是1,以此类推。

5.2文本数据的提取

如果要处理中文文档,需要把文章里的各个词汇中间打上空格,否则会把整个一句话当做一个词汇。这个就需要借助一个包叫jieba。打开anaconda prompt:

pip install jieba

文档特征提取的api是sklearn.feature_extraction.text.CountVectorizer

import pandas as pd 
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
import jieba as jb

cont1=list(jb.cut(\"我有一头小毛驴我从来也不骑\"))
cont2=list(jb.cut(\"门前大桥下游过一群鸭,快来快来数一数,二四六七八\"))
print(cont1)
[\'我\', \'有\', \'一头\', \'小毛驴\', \'我\', \'从来\', \'也\', \'不\', \'骑\']
print(cont2)
[\'门前\', \'大桥\', \'下游\', \'过\', \'一群\', \'鸭\', \',\', \'快来\', \'快来\', \'数一数\', \',\', \'二四六\', \'七八\']

c=CountVectorizer()
data=c.fit_transform(cont2)
print(data)
 (0, 7)	1
  (1, 4)	1
  (2, 2)	1
  (4, 0)	1
  (7, 5)	1
  (8, 5)	1
  (9, 6)	1
  (11, 3)	1
  (12, 1)	1
  
#转化成DataFrame
df=pd.DataFrame(columns=c.get_feature_names(),data=data.toarray())
print(df)
 一群  七八  下游  二四六  大桥  快来  数一数  门前
0    0   0   0    0   0   0    0   1
1    0   0   0    0   1   0    0   0
2    0   0   1    0   0   0    0   0
3    0   0   0    0   0   0    0   0
4    1   0   0    0   0   0    0   0
5    0   0   0    0   0   0    0   0
6    0   0   0    0   0   0    0   0
7    0   0   0    0   0   1    0   0
8    0   0   0    0   0   1    0   0
9    0   0   0    0   0   0    1   0
10   0   0   0    0   0   0    0   0
11   0   0   0    1   0   0    0   0
12   0   1   0    0   0   0    0   0

特征提取之后,它会统计每个词出现的次数。这里注意,\"门前大桥下游过一群鸭,快来快来数一数,二四六七八\"这句话里分解出13个部分:

[\'门前\', \'大桥\', \'下游\', \'过\', \'一群\', \'鸭\', \',\', \'快来\', \'快来\', \'数一数\', \',\', \'二四六\', \'七八\']

所以矩阵有13行,但是仅统计字符数目大于1的词汇。这一点务必牢记。
另外有一个坑CountVectorizer是没有sparse这个参数的,但是sparse矩阵可以用.toarray()方法转化成numpy的ndarray类型数据。

data.toarray()

array([[0, 0, 0, 0, 0, 0, 0, 1],
       [0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [1, 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, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0]], dtype=int64)

总结

入门机器学习并不难,sklearn包非常友好,初学者可以运用各种api的估计器拟合自己的数据进行体验。我把这种方法叫做.fit()大法。但愿这篇文章可以让你体验机器学习的乐趣。限于本人水平,文中的错误还希望读者指出。谢谢!

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号