sklearn库的基本使用

文章目录

  • 1. sklearn 一般流程
    • 1.1 准备数据
    • 1.2 分割训练集、测试集
    • 1.3 训练并验证数据
  • 2. 管道Pipe
    • 2.1 预处理数据
    • 2.2 Pipe
  • 3. 交叉验证
  • 4. 超参数优化
  • 5. 异构数据
    • 5.1 导入数据
    • 5.2 划分数据集
  • 5.3 训练拟合
    • 5.4 One-hot 编码
    • 5.5 重新训练拟合
  • 6. 评价指标选择
    • 6.1 二分类
    • 6.2 多分类
    • 6.3 回归问题

1. sklearn 一般流程

1.1 准备数据

这里的数据集我们使用内置的鸢尾花数据集来进行测试,

from sklearn.datasets import load_iris
iris = load_iris()

1.2 分割训练集、测试集

将鸢尾花数据集的数据和标签分割成训练集和测试集,其中测试集占比20%.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(iris['data'], iris['target'], test_size=0.2)

1.3 训练并验证数据

在这里使用逻辑回归进行拟合数据

from sklearn.linear_model import LogisticRegression

# 以下参数依次表示,使用拟牛顿法求局部最优,多分类的训练方式是 'ovr',最大迭代次数是5000,随机状态为42
clf = LogisticRegression(solver='lbfgs', multi_class='ovr', max_iter=5000, random_state=42)
clf.fit(X_train, y_train)
accuracy = clf.score(X_test, y_test)
print('Accuracy score of the {} is {:.2f}'.format(clf.__class__.__name__, accuracy))

怎么样,使用起来是不是很简单,使用不同的模型需要改变的就只有上面的 LogisticRegression 分类器和里面的参数,这些改变起来非常的容易,下面我们再对这个流程进行优化。

2. 管道Pipe

2.1 预处理数据

在对数据进行拟合前,我们可以对数据进行一些预处理操作,比如归一化。归一化将数据都化为[0,1]区间内,这样能够十分有效的节省迭代的次数,这是很简单的一个道理,拟合[0,1] 区间的数据肯定会比拟合不知多大界限的数据要容易得多,sklearn中的标准化一般使用 MinMaxScaler 类,使用缩放器对其进行缩放,示例如下:

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

注意,我们不能对测试集中的数据也使用 fit_transform 函数, 该函数实际上是将 fit 函数与 transform 函数合在一起了, fit 函数能够找到数据集中的最大值与最小值, transform 函数能够使用该最大最小值对数据进行归一化缩放,测试集中的数据是不允许进行改变的,如果对测试集中的数据也使用 fit_transform 则相当于改变了测试集数据的标准,所以仅对测试集使用 transform 函数来统一标准。

2.2 Pipe

上述过程其实可以使用管道进行简化,可以在管道中对想要进行的估计器进行命名,pipe 简化后的代码如下所示:

from sklearn.pipeline import make_pipeline

pipe = make_pipeline(MinMaxScaler(),
                     LogisticRegression(solver='lbfgs', multi_class='auto', random_state=42, max_iter=1000))
pipe.fit(X_train, y_train)
accuracy = pipe.score(X_test, y_test)
print('Accuracy score of the {} is {:.2f}'.format(pipe.__class__.__name__, accuracy))

3. 交叉验证

当数据较少时,由于我们还要对其进行训练集和测试集的分割,所以可使用的数据更加少了,这种情况下一般会使用K折交叉验证法来对数据进行验证,这种情况下也就不需要对数据进行训练集与测试集的分割了,具体方法陈述如下。

K K K 折交叉验证:首先随机地将已给数据切分为 K K K 个互不相交、大小相同的子集;然后利用 K − 1 K-1 K1 个子集的数据训练模型,利用余下的子集测试模型;将这一过程对可能的 K K K 种选择重复进行;最后选出 K K K 次评测中平均测试误差最小的模型。

使用交叉验证的代码如下:

from sklearn.model_selection import cross_val_score

pipe = make_pipeline(MinMaxScaler(),
                     LogisticRegression(solver='lbfgs', multi_class='auto', random_state=42, max_iter=1000))

# 参数依次为传入的模型,数据集,标签集,cv为K折交叉中K的值,scoring为评价函数
score = cross_val_score(pipe, iris['data'],iris['target'],cv=10,scoring='accuracy')
print(score.mean())

返回的 score 是一个列表,列表中的每一项是每一折拟合的评分,最后对其进行求平均值进行评估。

4. 超参数优化

管道组件的参数不同,其准确度也是不一样的,很多时候我们都想找到最适合的参数来对模型进行拟合,从而获得最佳精度。

我们可以使用 pipe.get_params() 来获得管道的参数,如以上模型使用该函数输出管道的参数如下:

{'memory': None,
 'steps': [('minmaxscaler', MinMaxScaler()), ('logisticregression', LogisticRegression(max_iter=1000, random_state=42))],
   'verbose': False, 
   'minmaxscaler': MinMaxScaler(),
   'logisticregression': LogisticRegression(max_iter=1000, random_state=42),
   'minmaxscaler__clip': False, 
   'minmaxscaler__copy': True, 
   'minmaxscaler__feature_range': (0, 1), 
   'logisticregression__C': 1.0, 
   'logisticregression__class_weight': None, 
   'logisticregression__dual': False, 
   'logisticregression__fit_intercept': True, 
   'logisticregression__intercept_scaling': 1, 
   'logisticregression__l1_ratio': None, 
   'logisticregression__max_iter': 1000, 
   'logisticregression__multi_class': 'auto', 
   'logisticregression__n_jobs': None, 
   'logisticregression__penalty': 'l2', 
   'logisticregression__random_state': 42, 
   'logisticregression__solver': 'lbfgs', 
   'logisticregression__tol': 0.0001, 
   'logisticregression__verbose': 0, 
   'logisticregression__warm_start': False}

一个简单的调节超参数的想法是循环进行拟合,选择拟合精度最高的那一组参数作为最终的拟合模型,sklearn的 GridSearchCV 函数能够帮我们做到。

比如我们希望优化上述管道的分类 logisticregression__Clogisticregression__penalty 参数,则有下述代码,

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import MinMaxScaler
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import GridSearchCV

iris = load_iris()

pipe = make_pipeline(MinMaxScaler(),
                     LogisticRegression(solver='saga', multi_class='auto', random_state=42, max_iter=10000))

param_grid = {'logisticregression__C': [0.1, 1.0, 10],
              'logisticregression__penalty': ['l2', 'l1']}

# 参数依次是估计器,优化的参数,K折检验,n_jobs=-1表示使用全部的cpu
grid = GridSearchCV(pipe, param_grid=param_grid, cv=3, n_jobs=-1, return_train_score=True, scoring='accuracy')
grid.fit(iris['data'], iris['target'])

# 得到要搜索的参数中最优的参数组合
print(grid.best_params_)

5. 异构数据

我们知道刚才都使用的是数值类型的数据来对模型进行拟合,但是,实际中我们不可避免地会使用数值类型的数据,二这些非数值类型的数据我们称之为异构数据。

在这里我们使用泰坦尼克号中的幸存者遇难者数据来进行示例,数据我放到网盘上(提取码1234),需要用到的自行下载。

5.1 导入数据

这里使用pandas对训练集中的数据进行导入。

import pandas as pd

data = pd.read_csv(r'F:data\titanic\train.csv', na_values='?')
print(data.head())

5.2 划分数据集

我们需要预测的是其是否幸存或死亡,所以我们的 x 为除了幸存之外的所有列, y 为幸存那一列。

from sklearn.model_selection import train_test_split
y = data['Survived']
# 将无用的数据以及结果删掉
x = data.drop(columns=['Survived','PassengerId', 'Pclass', 'Name', 'Ticket'])

x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=42)

5.3 训练拟合

一般情况下我们是像下面一样拟合的,但是这样的话由于存在异构数据,一定会报错。

from sklearn.linear_model import LogisticRegression

clf = LogisticRegression()
clf.fit(X_train, y_train)#这里肯定会报错。

为了不让这些异构数据影响到我们的训练,我们需要想办法将异构数据转为数值类型的数据,最常用最简单的办法就是使用 one-hot 矩阵。

5.4 One-hot 编码

我们以 sexembarked 列,将使用 SimpleImputer 用常量值替换缺失值,对其做one-hot编码如下:

from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import make_pipeline

ohe = make_pipeline(SimpleImputer(strategy='constant'), OneHotEncoder())
X_encoded = ohe.fit_transform(x_train[['Sex', 'Embarked']])
print(X_encoded.toarray())

输出时可以看到矩阵的值为数值,可以进行拟合。

5.5 重新训练拟合

在处理数据时,我们要将数值和能够转化为 one-hot 矩阵的列分开来,如下:

col_cat = ['Sex', 'Embarked']
col_num = ['Age', 'Sibsp', 'Parch', 'Fare']

pipe_cat = make_pipeline(SimpleImputer(strategy='constant'), OneHotEncoder(handle_unknown='ignore'))
pipe_num = make_pipeline(SimpleImputer(), StandardScaler())

# 能够将多个列管道拼接在一起,在拼接时未指定的列将会被删掉
preprocessor = make_column_transformer((pipe_cat, col_cat), (pipe_num, col_num))

pipe = make_pipeline(preprocessor, LogisticRegression(solver='lbfgs'))

pipe.fit(x_train, y_train)
accuracy = pipe.score(x_test, y_test)
print('Accuracy score of the {} is {:.2f}'.format(pipe.__class__.__name__, accuracy))

当然,这里也可以使用网格搜索 GridSearchCV 来对参数进行优化。

6. 评价指标选择

6.1 二分类

准确度

将二分类中的分类指标与预测的分类指标进行比对,计算出其中分类准确的样本比例,公式如下:
a c c = ∑ i = 1 N I ( y i ^ = y ) acc=\sum_{i=1}^NI(\hat{y_i}=y) acc=i=1NI(yi^=y)sklearn中的函数如下所示

from sklearn.metrics import accuracy_score
acc=accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)

参数如下:
y_true:数据的真实label值
y_pred:数据的预测标签值
normalize:默认为True,返回正确预测的个数,若是为False,返回正确预测的比例
sample_weight:样本权重

混淆矩阵

from sklearn.metrics import confusion_matrix
conf = confusion_matrix(y_true,y_pred,labels=None,sample_weight = None)

y_true:真实的label,一维数组,列名
y_pred:预测值的label,一维数组,行名
labels:默认不指定,此时y_true,y_pred去并集,做升序,作为label
sample_weight:样本权重
返回结果:返回混淆矩阵

精确度和召回率

TP:将正类预测为正类数;FN:将正类预测为负类数;FP:将负类预测为正类数;TN:将负类预测为负类数。
则精确度 P 和 召回率 R 表示如下:
P = T P T P + F P P= \frac{TP}{TP+FP} P=TP+FPTP R = T P T P + F N R=\frac{TP}{TP+FN} R=TP+FNTP那么设置召回率有什么作用呢?假设我们现在有100个患者样本,其中有5个患者患有癌症,我们用1表示,其余95名正常患者我们用0表示。假设我们现在用一种算法做预测,所有的结果都预测为0,95个肯定是预测对了,算法准确率为95%,看着挺高的。但是这个算法对于癌症患者的预测准确率是0,所以这个算法是没有任何意义的。这时候我们的recall值的价值就体现出来了,recall值是在5个癌症患者中找能预测出来的,如果预测3个对了,recall = 60%。

在sklearn中,精确度与召回率函数如下:

from sklearn.metrics import classification_report
classification=classification_report(y_true, y_pred, labels=None, 
target_names=None, sample_weight=None, digits=2, output_dict=False)

y_true:真实的label,一维数组,列名
y_pred:预测值的label,一维数组,行名
labels:默认不指定,此时y_true,y_pred去并集,做升序,做label
sample_weight:样本权重
target_names:行标签,顺序和label的要一致
digits:整型,小数的位数
out_dict:输出格式,默认False,如果为True,输出字典。
输出为一个矩阵形式,包含每一个类别的精确度,召回率,F1。

6.2 多分类

多分类经常使用的评价指标也是上面三个,那就如上所示吧

6.3 回归问题

决定系数R2
决定系数R2定义如下所示
R 2 = 1 − ∑ i = 0 N ( y i − y i ^ ) 2 ∑ i = 0 N ( y i − y i ˉ ) 2 R2=1-\frac{\sum_{i=0}^N(y_i-\hat{y_i})^2}{\sum_{i=0}^N(y_i-\bar{y_i})^2} R2=1i=0N(yiyiˉ)2i=0N(yiyi^)2决定系数,也称为拟合优度。是相关系数的平方。表示可根据自变量的变异来解释因变量的变异部分。决定系数的大小决定了相关的密切程度。意义:拟合优度越大,自变量对因变量的解释程度越高,自变量引起的变动占总变动的百分比高。观察点在回归直线附近越密集。

在sklearn中的使用如下:

from sklearn.metrics import r2_score
r2 = r2_score(y_true,y_pred) 

均方差

均方差是最常用的回归问题的损失函数,表示如下:
M S E = 1 N ∑ i = 1 N ( y i − y i ^ ) 2 MSE= \frac{1}{N}\sum_{i=1}^N(y_i-\hat{y_i})^2 MSE=N1i=1N(yiyi^)2在sklearn中的使用如下所示:

from sklearn.metrics import mean_squared_error # 均方误差
mse = mean_squared_error(y_true,y_pred)

你可能感兴趣的:(机器学习,sklearn,机器学习,python)