赞
踩
这里的数据集我们使用内置的鸢尾花数据集来进行测试,
from sklearn.datasets import load_iris
iris = load_iris()
将鸢尾花数据集的数据和标签分割成训练集和测试集,其中测试集占比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)
在这里使用逻辑回归进行拟合数据
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
分类器和里面的参数,这些改变起来非常的容易,下面我们再对这个流程进行优化。
在对数据进行拟合前,我们可以对数据进行一些预处理操作,比如归一化。归一化将数据都化为[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
函数来统一标准,这种错误也被称为数据泄露。
管道的使用在sklearn中实际上非常省力。前面提到的两个模式是数据泄漏的问题。然而,当必须手动进行预处理时,很难防止这种错误。因此,sklearn 引入了Pipeline对象。它依次连接多个转换器和分类器(或回归器)。我们可以创建一个如下管道:
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))
管道里的转换器具有相同的API。 我们使用管道的 fit
来训练分类器并用 socre
来检查准确性。对管道调用 fit
会调用管道中所有变换器的 fit_transform
方法。 调用 score
(或 predict
和 predict_proba
)将调用管道中所有转换器的内部变换。
当数据较少时,由于我们还要对其进行训练集和测试集的分割,所以可使用的数据更加少了,这种情况下一般会使用K折交叉验证法来对数据进行验证,这种情况下也就不需要对数据进行训练集与测试集的分割了,具体方法陈述如下。
K K K 折交叉验证:首先随机地将已给数据切分为 K K K 个互不相交、大小相同的子集;然后利用 K − 1 K-1 K−1 个子集的数据训练模型,利用余下的子集测试模型;将这一过程对可能的 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
是一个列表,列表中的每一项是每一折拟合的评分,最后对其进行求平均值进行评估。
管道组件的参数不同,其准确度也是不一样的,很多时候我们都想找到最适合的参数来对模型进行拟合,从而获得最佳精度。
我们可以使用 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__C
和 logisticregression__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_)
我们知道刚才都使用的是数值类型的数据来对模型进行拟合,但是,实际中我们不可避免地会使用数值类型的数据,二这些非数值类型的数据我们称之为异构数据。
在这里我们使用泰坦尼克号中的幸存者遇难者数据来进行示例,数据我放到网盘上(提取码1234),需要用到的自行下载。
这里使用pandas对训练集中的数据进行导入。
import pandas as pd
data = pd.read_csv(r'F:data\titanic\train.csv', na_values='?')
print(data.head())
我们需要预测的是其是否幸存或死亡,所以我们的 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)
一般情况下我们是像下面一样拟合的,但是这样的话由于存在异构数据,一定会报错。
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression()
clf.fit(X_train, y_train)#这里肯定会报错。
为了不让这些异构数据影响到我们的训练,我们需要想办法将异构数据转为数值类型的数据,最常用最简单的办法就是使用 one-hot
矩阵。
我们以 sex
与 embarked
列,将使用 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())
输出时可以看到矩阵的值为数值,可以进行拟合。
在处理数据时,我们要将数值和能够转化为 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
来对参数进行优化。
准确度
将二分类中的分类指标与预测的分类指标进行比对,计算出其中分类准确的样本比例,公式如下:
a
c
c
=
∑
i
=
1
N
I
(
y
i
^
=
y
)
acc=\sum_{i=1}^NI(\hat{y_i}=y)
acc=i=1∑NI(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。
多分类经常使用的评价指标也是上面三个,那就如上所示吧
决定系数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=1−∑i=0N(yi−yiˉ)2∑i=0N(yi−yi^)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=1∑N(yi−yi^)2在sklearn中的使用如下所示:
from sklearn.metrics import mean_squared_error # 均方误差
mse = mean_squared_error(y_true,y_pred)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。