@浙大疏锦行复习日
仔细回顾一下之前21天的内容,没跟上进度的同学补一下进度。
作业:
自行学习参考如何使用kaggle平台,写下使用注意点,并对下述比赛提交代码
导入需要的库
import pandas as pd # 用于数据处理和分析,可处理表格数据。
import numpy as np # 用于数值计算,提供了高效的数组操作。
import matplotlib.pyplot as plt # 用于绘制各种类型的图表
import seaborn as sns # 基于matplotlib的高级绘图库,能绘制更美观的统计图形。
import warnings
from sklearn.preprocessing import StandardScaler,MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier #随机森林分类器
from sklearn.metrics import make_scorer,accuracy_score, precision_score, recall_score, f1_score # 用于评估分类器性能的指标
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
plt.rcParams['figure.dpi'] = 300
warnings.filterwarnings("ignore")
# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
train = pd.read_csv('train.csv') # 读取数据
print(train.isnull().sum())
Survived 是否存活(label)
PassengerId (乘客ID)
Pclass(用户阶级):1 - 1st class,高等用户;2 - 2nd class,中等用户;3 - 3rd class,低等用户;
Name(名字)
Sex(性别)
Age(年龄)
SibSp:描述了泰坦尼克号上与乘客同行的兄弟姐妹(Siblings)和配偶(Spouse)数目;
Parch:描述了泰坦尼克号上与乘客同行的家长(Parents)和孩子(Children)数目;
Ticket(船票号)
Fare(乘客费用)
Cabin(船舱)
Embarked(港口):用户上船时的港口
PassengerId(乘客ID),Name(姓名),Ticket(船票信息)存在唯一性,三类意义不大,可以考虑不加入后续的分析
看一下训练集有没有缺失值
可以看到Age,Cabin,Embarked有缺失值
#对Age使用中位数填充
median_income = train['Age'].median()
train['Age'].fillna(median_income, inplace=True)mode = train['Embarked'].mode()
print(mode)
mode = mode[0]
# 众数填补
train['Embarked'].fillna(mode, inplace=True)
# 检查下是否有缺失值
print(train['Embarked'].isnull().sum())# 对 Cabin 列的缺失值填充为 'U'
train['Cabin'] = train['Cabin'].fillna('U')
print(train.isnull().sum())
现在已无缺失值
对数据做一下分析
对数据的认识是十分重要的,所以我们在这里进行对各个字段的分析,看看每个属性与最后的Survived有什么关系
# 统计存活(Survived=1)和死亡(Survived=0)的人数
survived_counts = train['Survived'].value_counts()# 设置Seaborn风格
sns.set_style('ticks')# 配置中文字体,解决中文显示异常问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 创建画布,设置饼图为正圆形(figsize设为正方形)
fig, ax = plt.subplots(figsize=(6, 6))# 绘制饼图
survived_counts.plot.pie(ax=ax,autopct='%1.2f%%', # 显示百分比,保留2位小数labels=['死亡', '存活'], # 自定义图例标签colors=['#FF6B6B', '#4ECDC4'], # 自定义颜色,红色代表死亡,青色代表存活startangle=90, # 饼图从正上方开始绘制textprops={'fontsize': 12} # 设置百分比文字大小
)# 设置标题
ax.set_title('泰坦尼克号乘客存活比例', fontsize=14, fontweight='bold', pad=20)
ax.set_ylabel('') # 移除默认的y轴标签# 移除顶部和右侧的边框,让图表更简洁
sns.despine(top=True, right=True)# 自动调整布局,防止元素重叠
plt.tight_layout()
plt.show()
在这次中,大约有38.38%的人存活了下来
分别看一下各属性的基本分布情况,首先我们对适合利用图形展示的属性,通过绘图的方式探查属性的分布,分类型和数值型数据非常适合绘图,所以这部分我们选择乘客等级、性别、年龄、票价和登船港口五类属性。
# 绘图
fig = plt.figure()
# 乘客等级分布
plt.subplot2grid((2, 3), (0, 0))
train['Pclass'].value_counts().plot(kind='bar')
plt.ylabel(u"人数")
plt.xlabel(u'乘客等级')
plt.title(u'乘客等级分布')# 乘客性别分布
plt.subplot2grid((2, 3), (0, 1))
train['Sex'].value_counts().plot(kind='bar')
plt.ylabel(u"人数")
plt.xlabel(u'性别')
plt.title(u'乘客性别分布')# 乘客的年龄分布
plt.subplot2grid((2, 3), (0, 2))
train['Age'].hist()
plt.xlabel(u'年龄')
plt.title(u'乘客年龄分布')# 票价的分布
plt.subplot2grid((2, 3), (1, 0))
train['Fare'].hist()
plt.xlabel(u'票价')
plt.title(u'船票票价分布')# 箱线图:票价的异常情况探查
plt.subplot2grid((2, 3), (1, 1))
train['Fare'].plot(kind='box')
plt.title(u'票价箱线图')# 登船港口的分布情况
plt.subplot2grid((2, 3), (1, 2))
train['Embarked'].value_counts().plot(kind='bar')
plt.xlabel(u'登船口')
plt.title(u'登船口乘客量分布')
plt.show()
对于乘客等级、性别、登船口这类类别型的属性,从柱状图上探查各类的分布情况,而对于年龄和票价这类连续型的属性,我们可以选择利用直方图查看属性的分布。从乘客等级分布的柱状图上,我们得到三等乘客人数最多,1等和2等的乘客相对较少(等级顺序:1>2>3);在性别上,男性多于女性;在登船港口上,发现人数从高到低的港口分别是S>C>Q;看一下年龄的分布情况,我们发现20~30岁区间的乘客人数最多。
分析Sex
# 男性和女性存活情况
train[['Sex','Survived']].groupby('Sex').mean().plot.bar()survive_sex=train.groupby(['Sex','Survived'])['Survived'].count()print('女性存活率%.2f%%,男性存活率%.2f%%' %(survive_sex.loc['female',1]/survive_sex.loc['female'].sum()*100,survive_sex.loc['male',1]/survive_sex.loc['male'].sum()*100))
plt.tight_layout()
plt.show()
女性存活率74.20%,男性存活率18.89%
从数据结果可以得出,女性存活率是更高的
分析Age
g = sns.FacetGrid(train, col='Survived')
g.map(plt.hist, 'Age', bins=20)
plt.tight_layout()
plt.show()
从上图可以看出,Age与survived是有关系的,因此需要作为特征保存
分析登陆港口
# 绘图
plt.figure(figsize=(10, 8), dpi=100)# 乘客的等级和获救情况的关系, 从结果上发现,1和2等级的乘客获救率明显高于3等级的乘客
p1 = plt.subplot(221)
Pclass_0 = train.loc[train['Survived'] == 0, 'Pclass'].value_counts()
Pclass_1 = train.loc[train['Survived'] == 1, 'Pclass'].value_counts()
df_pclass = pd.DataFrame({u'获救':Pclass_1,u'未获救':Pclass_0})
df_pclass.plot(kind='bar', ax=p1)
plt.title(u'不同等级乘客的获救情况')# 同样的方法,我们看一下性别和获救情况的关系,结果非常明显,女性比男性的获救率高
p2 = plt.subplot(222)
Survived_m = train.loc[train['Sex'] == 'male', 'Survived'].value_counts()
Survived_f = train.loc[train['Sex'] == 'female', 'Survived'].value_counts()
df_sex = pd.DataFrame({u'男性':Survived_m, u'女性':Survived_f})
df_sex.plot(kind='bar', stacked=True, ax=p2)
plt.title(u'不同性别乘客的获救情况')# 年龄划分,划分的标准:0~10为儿童;10~60为成年人;60及以上为老年人
p3 = plt.subplot(223)
bins = [min(train['Age']), 10, 60, max(train['Age'])]
bins_label = ['10岁及以下', '10-60岁', '60岁以上']
train['Age_cut'] = pd.cut(train['Age'], bins=bins, labels=bins_label)
print(train['Age_cut'].value_counts())
# 再对数据进行统计,结果发现儿童的获救率明显高于成年人和老年人
Age_0 = train.loc[train['Survived'] == 0, 'Age_cut'].value_counts()
Age_1 = train.loc[train['Survived'] == 1, 'Age_cut'].value_counts()
df_age = pd.DataFrame({u'获救':Age_1, u'未获救':Age_0})
df_age.plot(kind='bar', ax=p3)
plt.title(u'不同年龄阶段乘客的获救情况')
plt.show()
从图中得的以下结论:等级高的乘客获救率高(1>2>3);女性获救率远大于男性
其次,针对类别较多的SibSp和Parch属性,我们直接统计各类的是否获救情况。
# 堂兄弟妹个数以及父母子女个数的获救情况统计
g1 = train.groupby(['SibSp', 'Survived'])
df_SibSp = pd.DataFrame(g1.count()['PassengerId'])
df_SibSp.rename(columns={'PassengerId':'count'}, inplace=True)
print(df_SibSp)g2 = train.groupby(['Parch', 'Survived'])
df_Parch = pd.DataFrame(g2.count()['PassengerId'])
df_Parch.rename(columns={'PassengerId': 'count'}, inplace=True)
print(df_Parch)
从结果中,我们发现,SibSp<3和Parch<3的情况下,获救率更高。
分析Fare
print(train.loc[train['Fare'] == 0, 'Survived'].value_counts())
print(train.loc[train['Fare'] == max(train['Fare']), 'Survived'].value_counts())
plt.show()
结果发现,票价为0的15名乘客,仅有1人获救,而票价最高的三名乘客,全部获救,这说明了票价的高低对是否获救存在影响
#删除无用特征Name、Ticket 、Cabin
train= train.drop(columns=["Name","Ticket","Cabin"])#接下来对sex、embarked进行独热编码
# 对Sex、Embarked进行独热编码
train["Sex"] = pd.get_dummies(train["Sex"], dtype=int, drop_first=True)
train_data = pd.concat([train.drop("Embarked", axis=1),pd.get_dummies(train["Embarked"], prefix="Embarked", dtype=int, drop_first=False)], axis=1)# 查看数据
print(train_data.head(10))#对测试集进行处理
# 删除无用特征Name、Ticket 、Cabin,补全缺失值
test = pd.read_csv('test.csv') # 读取数据
test = test.drop(columns=["Name", "Ticket", "Cabin"])# 连续
continuous_features = test.select_dtypes(include=['float64', 'int64']).columns.tolist()
# 离散
discrete_features = test.select_dtypes(exclude=['float64', 'int64']).columns.tolist()# 离散特征使用众数进行补全
for feature in discrete_features:if test[feature].isnull().sum() > 0:mode_value = test[feature].mode()[0]test[feature].fillna(mode_value, inplace=True)# 连续变量用中位数进行补全
for feature in continuous_features:if test[feature].isnull().sum() > 0:median_value = test[feature].median()test[feature].fillna(median_value, inplace=True)
print(test.info())print(test.head(10))# 对Sex、Embarked进行独热编码
test["Sex"] = pd.get_dummies(test["Sex"], dtype=int, drop_first=True)
test_data = pd.concat([test.drop("Embarked", axis=1),pd.get_dummies(test["Embarked"], prefix="Embarked", dtype=int, drop_first=False)], axis=1)# 查看数据
print(test_data.head(10))from sklearn.model_selection import train_test_split
X = train_data.drop(['Survived'], axis=1) # 特征,axis=1表示按列删除
y = train_data['Survived'] # 标签
# 按照8:2划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 80%训练集,20%测试集# SVM
svm_model = SVC(random_state=42)
svm_model.fit(X_train, y_train)
svm_pred = svm_model.predict(X_test)print("\nSVM 分类报告:")
print(classification_report(y_test, svm_pred)) # 打印分类报告
print("SVM 混淆矩阵:")
print(confusion_matrix(y_test, svm_pred)) # 打印混淆矩阵# 计算 SVM 评估指标,这些指标默认计算正类的性能
svm_accuracy = accuracy_score(y_test, svm_pred)
svm_precision = precision_score(y_test, svm_pred)
svm_recall = recall_score(y_test, svm_pred)
svm_f1 = f1_score(y_test, svm_pred)
print("SVM 模型评估指标:")
print(f"准确率: {svm_accuracy:.4f}")
print(f"精确率: {svm_precision:.4f}")
print(f"召回率: {svm_recall:.4f}")
print(f"F1 值: {svm_f1:.4f}")# KNN
knn_model = KNeighborsClassifier()
knn_model.fit(X_train, y_train)
knn_pred = knn_model.predict(X_test)print("\nKNN 分类报告:")
print(classification_report(y_test, knn_pred))
print("KNN 混淆矩阵:")
print(confusion_matrix(y_test, knn_pred))knn_accuracy = accuracy_score(y_test, knn_pred)
knn_precision = precision_score(y_test, knn_pred)
knn_recall = recall_score(y_test, knn_pred)
knn_f1 = f1_score(y_test, knn_pred)
print("KNN 模型评估指标:")
print(f"准确率: {knn_accuracy:.4f}")
print(f"精确率: {knn_precision:.4f}")
print(f"召回率: {knn_recall:.4f}")
print(f"F1 值: {knn_f1:.4f}")# 逻辑回归
logreg_model = LogisticRegression(random_state=42)
logreg_model.fit(X_train, y_train)
logreg_pred = logreg_model.predict(X_test)print("\n逻辑回归 分类报告:")
print(classification_report(y_test, logreg_pred))
print("逻辑回归 混淆矩阵:")
print(confusion_matrix(y_test, logreg_pred))logreg_accuracy = accuracy_score(y_test, logreg_pred)
logreg_precision = precision_score(y_test, logreg_pred)
logreg_recall = recall_score(y_test, logreg_pred)
logreg_f1 = f1_score(y_test, logreg_pred)
print("逻辑回归 模型评估指标:")
print(f"准确率: {logreg_accuracy:.4f}")
print(f"精确率: {logreg_precision:.4f}")
print(f"召回率: {logreg_recall:.4f}")
print(f"F1 值: {logreg_f1:.4f}")# 朴素贝叶斯
nb_model = GaussianNB()
nb_model.fit(X_train, y_train)
nb_pred = nb_model.predict(X_test)print("\n朴素贝叶斯 分类报告:")
print(classification_report(y_test, nb_pred))
print("朴素贝叶斯 混淆矩阵:")
print(confusion_matrix(y_test, nb_pred))nb_accuracy = accuracy_score(y_test, nb_pred)
nb_precision = precision_score(y_test, nb_pred)
nb_recall = recall_score(y_test, nb_pred)
nb_f1 = f1_score(y_test, nb_pred)
print("朴素贝叶斯 模型评估指标:")
print(f"准确率: {nb_accuracy:.4f}")
print(f"精确率: {nb_precision:.4f}")
print(f"召回率: {nb_recall:.4f}")
print(f"F1 值: {nb_f1:.4f}")# 决策树
dt_model = DecisionTreeClassifier(random_state=42)
dt_model.fit(X_train, y_train)
dt_pred = dt_model.predict(X_test)print("\n决策树 分类报告:")
print(classification_report(y_test, dt_pred))
print("决策树 混淆矩阵:")
print(confusion_matrix(y_test, dt_pred))dt_accuracy = accuracy_score(y_test, dt_pred)
dt_precision = precision_score(y_test, dt_pred)
dt_recall = recall_score(y_test, dt_pred)
dt_f1 = f1_score(y_test, dt_pred)
print("决策树 模型评估指标:")
print(f"准确率: {dt_accuracy:.4f}")
print(f"精确率: {dt_precision:.4f}")
print(f"召回率: {dt_recall:.4f}")
print(f"F1 值: {dt_f1:.4f}")# 随机森林
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train)
rf_pred = rf_model.predict(X_test)print("\n随机森林 分类报告:")
print(classification_report(y_test, rf_pred))
print("随机森林 混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))rf_accuracy = accuracy_score(y_test, rf_pred)
rf_precision = precision_score(y_test, rf_pred)
rf_recall = recall_score(y_test, rf_pred)
rf_f1 = f1_score(y_test, rf_pred)
print("随机森林 模型评估指标:")
print(f"准确率: {rf_accuracy:.4f}")
print(f"精确率: {rf_precision:.4f}")
print(f"召回率: {rf_recall:.4f}")
print(f"F1 值: {rf_f1:.4f}")# XGBoost
xgb_model = xgb.XGBClassifier(random_state=42)
xgb_model.fit(X_train, y_train)
xgb_pred = xgb_model.predict(X_test)print("\nXGBoost 分类报告:")
print(classification_report(y_test, xgb_pred))
print("XGBoost 混淆矩阵:")
print(confusion_matrix(y_test, xgb_pred))xgb_accuracy = accuracy_score(y_test, xgb_pred)
xgb_precision = precision_score(y_test, xgb_pred)
xgb_recall = recall_score(y_test, xgb_pred)
xgb_f1 = f1_score(y_test, xgb_pred)
print("XGBoost 模型评估指标:")
print(f"准确率: {xgb_accuracy:.4f}")
print(f"精确率: {xgb_precision:.4f}")
print(f"召回率: {xgb_recall:.4f}")
print(f"F1 值: {xgb_f1:.4f}")# LightGBM
lgb_model = lgb.LGBMClassifier(random_state=42)
lgb_model.fit(X_train, y_train)
lgb_pred = lgb_model.predict(X_test)print("\nLightGBM 分类报告:")
print(classification_report(y_test, lgb_pred))
print("LightGBM 混淆矩阵:")
print(confusion_matrix(y_test, lgb_pred))lgb_accuracy = accuracy_score(y_test, lgb_pred)
lgb_precision = precision_score(y_test, lgb_pred)
lgb_recall = recall_score(y_test, lgb_pred)
lgb_f1 = f1_score(y_test, lgb_pred)
print("LightGBM 模型评估指标:")
print(f"准确率: {lgb_accuracy:.4f}")
print(f"精确率: {lgb_precision:.4f}")
print(f"召回率: {lgb_recall:.4f}")
print(f"F1 值: {lgb_f1:.4f}")
SVM 分类报告:
precision recall f1-score support
0 0.60 0.98 0.74 105
1 0.67 0.05 0.10 74
accuracy 0.60 179
macro avg 0.63 0.52 0.42 179
weighted avg 0.62 0.60 0.48 179
SVM 混淆矩阵:
[[103 2]
[ 70 4]]
SVM 模型评估指标:
准确率: 0.5978
精确率: 0.6667
召回率: 0.0541
F1 值: 0.1000
KNN 分类报告:
precision recall f1-score support
0 0.67 0.84 0.74 105
1 0.64 0.41 0.50 74
accuracy 0.66 179
macro avg 0.65 0.62 0.62 179
weighted avg 0.65 0.66 0.64 179
KNN 混淆矩阵:
[[88 17]
[44 30]]
KNN 模型评估指标:
准确率: 0.6592
精确率: 0.6383
召回率: 0.4054
F1 值: 0.4959
逻辑回归 分类报告:
precision recall f1-score support
0 0.79 0.88 0.83 105
1 0.79 0.68 0.73 74
accuracy 0.79 179
macro avg 0.79 0.78 0.78 179
weighted avg 0.79 0.79 0.79 179
逻辑回归 混淆矩阵:
[[92 13]
[24 50]]
逻辑回归 模型评估指标:
准确率: 0.7933
精确率: 0.7937
召回率: 0.6757
F1 值: 0.7299
朴素贝叶斯 分类报告:
precision recall f1-score support
0 0.83 0.77 0.80 105
1 0.70 0.77 0.74 74
accuracy 0.77 179
macro avg 0.77 0.77 0.77 179
weighted avg 0.78 0.77 0.77 179
朴素贝叶斯 混淆矩阵:
[[81 24]
[17 57]]
朴素贝叶斯 模型评估指标:
准确率: 0.7709
精确率: 0.7037
召回率: 0.7703
F1 值: 0.7355
决策树 分类报告:
precision recall f1-score support
0 0.78 0.79 0.79 105
1 0.70 0.69 0.69 74
accuracy 0.75 179
macro avg 0.74 0.74 0.74 179
weighted avg 0.75 0.75 0.75 179
决策树 混淆矩阵:
[[83 22]
[23 51]]
决策树 模型评估指标:
准确率: 0.7486
精确率: 0.6986
召回率: 0.6892
F1 值: 0.6939
随机森林 分类报告:
precision recall f1-score support
0 0.84 0.87 0.85 105
1 0.80 0.77 0.79 74
accuracy 0.83 179
macro avg 0.82 0.82 0.82 179
weighted avg 0.83 0.83 0.83 179
随机森林 混淆矩阵:
[[91 14]
[17 57]]
随机森林 模型评估指标:
准确率: 0.8268
精确率: 0.8028
召回率: 0.7703
F1 值: 0.7862
XGBoost 分类报告:
precision recall f1-score support
0 0.83 0.84 0.83 105
1 0.77 0.76 0.76 74
accuracy 0.80 179
macro avg 0.80 0.80 0.80 179
weighted avg 0.80 0.80 0.80 179
XGBoost 混淆矩阵:
[[88 17]
[18 56]]
XGBoost 模型评估指标:
准确率: 0.8045
精确率: 0.7671
召回率: 0.7568
F1 值: 0.7619
LightGBM 分类报告:
precision recall f1-score support
0 0.82 0.85 0.84 105
1 0.77 0.74 0.76 74
accuracy 0.80 179
macro avg 0.80 0.80 0.80 179
weighted avg 0.80 0.80 0.80 179
LightGBM 混淆矩阵:
[[89 16]
[19 55]]
LightGBM 模型评估指标:
准确率: 0.8045
精确率: 0.7746
召回率: 0.7432
F1 值: 0.7586
综上比较几种模型,感觉随机森林更好一点,其实还能再调参或者其它的工作使得准确率更高一点
# 对测试集进行预测
test_pred = rf_model.predict(test)# 创建提交文件
submission = pd.DataFrame({'PassengerId': test['PassengerId'], # 从测试数据中获取乘客ID'Survived': test_pred # 模型预测的结果
})# 保存为CSV文件
submission.to_csv('titanic_submission.csv', index=False)