声明:本文主要参考DataWhale开源学习——动手学数据分析,GitHub地址:https://github.com/datawhalechina/hands-on-data-analysis
#第一步依旧是准备工作导入库,数据
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from IPython.display import Image
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.rcParams['figure.figsize'] = (10, 6) # 设置输出图片大小
train = pd.read_csv('train.csv')
train.shape
(891, 12)
【思考】这些库的作用是什么呢?你需要查一查
【思考题回答】numpy,matplotlib,pandas是数据分析的三大基本库。
seaborn是在Matplotlib的基础上进行了更高级的API封装,因此可以进行更复杂的图形设计和输出的库。
%matplotlib inline:将matplotlib的图表直接嵌入到Notebook中。
特征工程是整个机器学习中非常重要的一部分,如何对数据进行特征提取对最终结果的影响非常大。在建模过程中,一般会优先考虑算法和参数,但是数据特征才决定了整体结果的上限,而算法和参数只决定了如何逼近这个上限。特征工程其实就是要从原始数据中找到最有价值的信息,并转换成计算机所能读懂的形式。
缺失值填充方法:
# 对分类变量进行填充
train['Cabin'] = train['Cabin'].fillna('NA')
train['Embarked'] = train['Embarked'].fillna('S')
# 对连续变量进行填充
train['Age'] = train['Age'].fillna(round(train['Age'].mean())) #年龄一般为整数,故加个四舍五入函数
# 检查缺失值比例
train.isnull().sum().sort_values(ascending=False)
Embarked 0
Cabin 0
Fare 0
Ticket 0
Parch 0
SibSp 0
Age 0
Sex 0
Name 0
Pclass 0
Survived 0
PassengerId 0
dtype: int64
这里采用pd.get_dummies()函数
进行虚拟变量转换,get_dummies是利用pandas实现one hot encode的方式。
#train.head()
# 取出所有的输入特征
data = train[['Pclass','Sex','Age','SibSp','Parch','Fare', 'Embarked']]
# 进行虚拟变量转换
data = pd.get_dummies(data)
data.head()
Pclass | Age | SibSp | Parch | Fare | Sex_female | Sex_male | Embarked_C | Embarked_Q | Embarked_S | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 3 | 22.0 | 1 | 0 | 7.2500 | 0 | 1 | 0 | 0 | 1 |
1 | 1 | 38.0 | 1 | 0 | 71.2833 | 1 | 0 | 1 | 0 | 0 |
2 | 3 | 26.0 | 0 | 0 | 7.9250 | 1 | 0 | 0 | 0 | 1 |
3 | 1 | 35.0 | 1 | 0 | 53.1000 | 1 | 0 | 0 | 0 | 1 |
4 | 3 | 35.0 | 0 | 0 | 8.0500 | 0 | 1 | 0 | 0 | 1 |
我们这里使用一个机器学习最常用的一个库(sklearn)来完成我们的模型的搭建
官网:https://scikit-learn.org/stable/
下面给出sklearn模型算法路径选择图
这里使用留出法划分数据集
【思考】
【思考回答】
任务提示1
train_test_split
train_test_split?
后回车即可看到from sklearn.model_selection import train_test_split
X = data
y = train['Survived']
#对数据集进行切割
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
# 查看数据形状
X_train.shape, X_test.shape
((668, 10), (223, 10))
【思考】什么情况下切割数据集的时候不用进行随机选取?
【思考回答】数据在进行切割前已经进行过切割处理的或数据集本身非常大的情况。
LinearRegression
混淆sklearn.linear_model
sklearn.ensemble
逻辑回归不是回归模型而是分类模型,在sklearn.linear_model
中,需要调节参数C(正则化系数)
from sklearn.linear_model import LogisticRegression
#采用默认参数
lr = LogisticRegression()
lr.fit(X_train,y_train)
print('训练集得分:{:.2f}'.format(lr.score(X_train,y_train)))
print('测试集得分:{:.2f}'.format(lr.score(X_test,y_test)))
训练集得分:0.80
测试集得分:0.78
# 调整参数后的逻辑回归模型
lr2 = LogisticRegression(C=100)
lr2.fit(X_train, y_train)
print('训练集得分:{:.2f}'.format(lr2.score(X_train,y_train)))
print('测试集得分:{:.2f}'.format(lr2.score(X_test,y_test)))
训练集得分:0.80
测试集得分:0.79
随机森林是集成学习
中的一种算法,通过并行训练一堆决策树来各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。
可参考:https://blog.csdn.net/yangyin007/article/details/82385967
这里采用sklearn.emsemble
模块,主要调节n_estimateors
和max_depth
from sklearn.ensemble import RandomForestClassifier
#采用默认参数
rfc = RandomForestClassifier()
rfc.fit(X_train,y_train)
print('训练集得分:{:.2f}'.format(rfc.score(X_train,y_train)))
print('测试集得分:{:.2f}'.format(rfc.score(X_test,y_test)))
训练集得分:0.97
测试集得分:0.82
#调整参数
rfc2 = RandomForestClassifier(n_estimators=80, max_depth=5)
rfc2.fit(X_train, y_train)
print("Training set score: {:.2f}".format(rfc2.score(X_train, y_train)))
print("Testing set score: {:.2f}".format(rfc2.score(X_test, y_test)))
Training set score: 0.86
Testing set score: 0.83
【思考】
【思考回答】
predict
能输出预测标签,predict_proba
则可以输出标签概率#预测标签
lr_predict = lr.predict(X_train)
lr_predict[:10]
array([0, 1, 1, 1, 0, 0, 1, 0, 1, 1], dtype=int64)
#预测概率
lr_pre = lr.predict_proba(X_train)
lr_pre[:10]
array([[0.62834351, 0.37165649],
[0.14872739, 0.85127261],
[0.47129261, 0.52870739],
[0.20331331, 0.79668669],
[0.86395534, 0.13604466],
[0.90416819, 0.09583181],
[0.13796589, 0.86203411],
[0.89506733, 0.10493267],
[0.05712809, 0.94287191],
[0.13565136, 0.86434864]])
【思考】
【思考回答】
可参考:https://blog.csdn.net/tianguiyuyu/article/details/80697223
sklearn.model_selection
from sklearn.model_selection import cross_val_score
lr = LogisticRegression()
score = cross_val_score(lr,X_train,y_train,cv=10)
score.mean()
0.7977425705696117
计算二分类问题的混淆矩阵
计算精确率、召回率以及f-分数
【思考】什么是二分类问题的混淆矩阵,理解这个概念,知道它主要是运算到什么任务中的
【思考回答】混淆矩阵是一个二维方阵,包含四个情况:
真实值是positive,模型认为是positive的数量(True Positive=TP)
真实值是positive,模型认为是negative的数量(False Negative=FN):这就是统计学上的第二类错误
真实值是negative,模型认为是positive的数量(False Positive=FP):这就是统计学上的第一类错误
真实值是negative,模型认为是negative的数量(True Negative=TN)
sklearn.metrics
模块classification_report
模块from sklearn.metrics import confusion_matrix
# 训练模型
lr = LogisticRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_train)
#计算混淆矩阵
cnf_matrix = confusion_matrix(y_train,pred)
def plot_confusion_matrix(cm, classes,
title='Confusion matrix',
cmap=plt.cm.Blues):
"""
This function prints and plots the confusion matrix.
"""
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
plt.colorbar()
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes, rotation=0)
plt.yticks(tick_marks, classes)
thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
plt.text(j, i, cm[i, j],
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label')
# 画混淆矩阵
import itertools
class_names = [0,1]
plt.figure()
plot_confusion_matrix(cnf_matrix
, classes=class_names
, title='Confusion matrix')
plt.show()
from sklearn.metrics import classification_report
# 精确率、召回率以及f1-score
print(classification_report(y_train, pred))
precision recall f1-score support
0 0.83 0.86 0.84 412
1 0.76 0.71 0.74 256
avg / total 0.80 0.80 0.80 668
sklearn.metrics
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_test, lr.decision_function(X_test))
plt.plot(fpr, tpr, label="ROC Curve")
plt.xlabel("FPR")
plt.ylabel("TPR (recall)")
# 找到最接近于0的阈值
close_zero = np.argmin(np.abs(thresholds))
plt.plot(fpr[close_zero], tpr[close_zero], 'o', markersize=10, label="threshold zero", fillstyle="none", c='k', mew=2)
plt.legend(loc=4)