day 22

泰坦尼克号生还人数预测

数据来源:Titanic - Machine Learning from Disaster | Kaggle

数据预处理

import pandas as pd
import pandas as pd    #用于数据处理和分析,可处理表格数据。
import numpy as np     #用于数值计算,提供了高效的数组操作。
import matplotlib.pyplot as plt    #用于绘制各种类型的图表
import seaborn as sns   #基于matplotlib的高级绘图库,能绘制更美观的统计图形。
from sklearn.preprocessing import StandardScaler, MinMaxScaler  #用于数据预处理,进行归一化
 
 # 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号

data1 = pd.read_csv('train.csv') # 读取训练集
data2 = pd.read_csv('test.csv')# 读取测试集

# 先筛选字符串变量 
discrete_features = data1.select_dtypes(include=['object']).columns.tolist()

对于Name特征,直接去除,不做处理

对于Sex特征,进行独热编码

对于Ticket特征,统计其出现次数,并进行分箱,然后进行独热编码

对于Cabin特征,提取其前缀,对前缀的种类进行独热编码

对于Embarked特征,直接进行独热编码

# 去除 Name 特征
data1.drop('Name', axis=1, inplace=True)
data2.drop('Name', axis=1, inplace=True)

# Sex 独热编码,记得需要将bool类型转换为数值

def one_hot_encode_and_convert(df, original_df):#对独热编码函数进行封装,方便后续调用

    # 对 Sex 列进行独热编码
    encoded_df = pd.get_dummies(df, columns=['Sex'])
    # 找出独热编码后新增的特征名
    new_columns = [col for col in encoded_df.columns if col not in original_df.columns]
    # 将新增的布尔类型列转换为整数类型
    for col in new_columns:
        df[col] = encoded_df[col].astype(int)
    # 删除原始的 Sex 列
    if 'Sex' in df.columns:
        df.drop('Sex', axis=1, inplace=True)
    return df

# 提前读取数据
train_data = pd.read_csv("train.csv")
test_data = pd.read_csv("test.csv")

# 对 data1 和 data2 进行处理
data1 = one_hot_encode_and_convert(data1, train_data)
data2 = one_hot_encode_and_convert(data2, test_data)
#对Ticket特征进行处理,将Ticket的频次进行分箱,然后对分箱结果进行独热编码

def process_ticket_feature(df):
    """
    对数据框中的 Ticket 特征进行处理,包括计算频次、分箱、独热编码,并删除中间列。

    参数:
    df (pandas.DataFrame): 输入的数据框,包含 'Ticket' 列。

    返回:
    pandas.DataFrame: 处理后的数据框。
    """
    # 计算每个 Ticket 的频次
    ticket_counts = df['Ticket'].value_counts()

    # 将频次映射到数据集中
    df['Ticket_Frequency'] = df['Ticket'].map(ticket_counts)

    # 对频次进行分箱
    bins = [0, 1, 5, np.inf]
    labels = ['Low', 'Medium', 'High']
    df['Ticket_Frequency_Bin'] = pd.cut(df['Ticket_Frequency'], bins=bins, labels=labels)

    # 对分箱结果进行独热编码
    ticket_bin_encoded = pd.get_dummies(df['Ticket_Frequency_Bin'], prefix='Ticket_Bin')
    
    # 将独热编码后的特征转换为整数类型
    ticket_bin_encoded = ticket_bin_encoded.astype(int)

    # 合并编码后的特征并删除中间列
    df = pd.concat([df, ticket_bin_encoded], axis=1)
    df = df.drop(['Ticket', 'Ticket_Frequency', 'Ticket_Frequency_Bin'], axis=1)

    return df


data1 = process_ticket_feature(data1)
data2 = process_ticket_feature(data2)
#对Cabin特征,提取其前缀,对前缀的种类进行独热编码

def process_cabin_feature(df):
    """
    对数据框中的 Cabin 特征进行处理,提取其前缀并进行独热编码。

    参数:
    df (pandas.DataFrame): 输入的数据框,包含 'Cabin' 列。

    返回:
    pandas.DataFrame: 处理后的数据框。
    """
    # 提取 Cabin 特征的前缀
    def extract_prefix(cabin):
        if pd.notna(cabin):
            return cabin[0]
        else:
            return 'NaN'
    
    df['Cabin_Prefix'] = df['Cabin'].apply(extract_prefix)
    
    # 对前缀进行独热编码
    cabin_prefix_encoded = pd.get_dummies(df['Cabin_Prefix'], prefix='Cabin')

    # 将独热编码后的特征转换为整数类型
    cabin_prefix_encoded = cabin_prefix_encoded.astype(int)
    
    # 合并编码后的特征并删除中间列
    df = pd.concat([df, cabin_prefix_encoded], axis=1)
    df = df.drop(['Cabin', 'Cabin_Prefix'], axis=1)
    
    return df


data1 = process_cabin_feature(data1)
data2 = process_cabin_feature(data2)
#Embarked特征独热编码

def one_hot_encode_embarked(df):
    """
    对数据框中的 Embarked 特征进行独热编码,并将编码结果转换为整数类型。

    参数:
    df (pandas.DataFrame): 输入的数据框,包含 'Embarked' 列。

    返回:
    pandas.DataFrame: 处理后的数据框。
    """
    # 对 Embarked 特征进行独热编码
    embarked_encoded = pd.get_dummies(df['Embarked'], prefix='Embarked')
    
    # 将独热编码结果转换为整数类型
    embarked_encoded = embarked_encoded.astype(int)
    
    # 合并编码后的特征到原始数据框
    df = pd.concat([df, embarked_encoded], axis=1)
    
    # 删除原始的 Embarked 列
    df = df.drop('Embarked', axis=1)
    
    return df


data1 = one_hot_encode_embarked(data1)
data2 = one_hot_encode_embarked(data2)
#缺失值用众数补充
def fill_missing_with_mode(df):
    """
    使用每列的众数填充数据框中的缺失值。

    参数:
    df (pandas.DataFrame): 输入的数据框。

    返回:
    pandas.DataFrame: 填充缺失值后的数据框。
    """
    for column in df.columns:
        # 计算每列的众数,取第一个值(因为众数可能有多个)
        mode_value = df[column].mode()[0]
        # 用众数填充该列的缺失值
        df[column].fillna(mode_value, inplace=True)
    return df


data1 = fill_missing_with_mode(data1)
data2 = fill_missing_with_mode(data2)

模型训练

# 划分数据集
from sklearn.model_selection import train_test_split
X = data1.drop(['Survived'], axis=1)  # 特征,axis=1表示按列删除
y = data1['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%测试集
from skopt import BayesSearchCV
from skopt.space import Integer, Categorical
import xgboost as xgb #XGBoost分类器
import lightgbm as lgb #LightGBM分类器
from sklearn.ensemble import RandomForestClassifier #随机森林分类器
from sklearn.metrics import classification_report, confusion_matrix
import time
import warnings #用于忽略警告信息
warnings.filterwarnings("ignore") # 忽略所有警告信息

# --- 1. 贝叶斯优化随机森林 ---
print("\n--- 1. 贝叶斯优化随机森林 (训练集 -> 测试集) ---")
# 定义要搜索的参数空间
search_space = {
    'n_estimators': (50, 500),
    'max_depth': (3, 20),
    'min_samples_split': (2, 20),
    'min_samples_leaf': (1, 10),
    'max_features': (0.1, 1.0),
}

# 创建贝叶斯优化搜索对象
bayes_search = BayesSearchCV(
    estimator=RandomForestClassifier(),
    search_spaces=search_space,
    n_iter=32,  # 迭代次数,可根据需要调整
    cv=5, # 5折交叉验证,这个参数是必须的,不能设置为1,否则就是在训练集上做预测了
    n_jobs=-1,
    scoring='accuracy'
)

start_time = time.time()
# 在训练集上进行贝叶斯优化搜索
bayes_search.fit(X_train, y_train)
end_time = time.time()

print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", bayes_search.best_params_)

# 使用最佳参数的模型进行预测
best_model = bayes_search.best_estimator_
best_pred = best_model.predict(X_test)

print("\n贝叶斯优化后的随机森林 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("贝叶斯优化后的随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))
# --- 2. 贝叶斯优化XGBoost ---
print("\n--- 2. 贝叶斯优化XGBoost (训练集 -> 测试集) ---")
# 定义要搜索的参数空间
search_space = {
    'n_estimators': (50, 500),
    'learning_rate': (0.01, 0.3),
    'max_depth': (3, 10),
    'min_child_weight': (1, 10),
    'subsample': (0.5, 1.0),
    'colsample_bytree': (0.5, 1.0)
}

# 创建贝叶斯优化搜索对象
bayes_search = BayesSearchCV(
    estimator=xgb.XGBClassifier(),
    search_spaces=search_space,
    n_iter=32,  # 迭代次数,可根据需要调整
    cv=5, # 5折交叉验证,这个参数是必须的,不能设置为1,否则就是在训练集上做预测了
    n_jobs=-1,
    scoring='accuracy'
)

start_time = time.time()
# 在训练集上进行贝叶斯优化搜索
bayes_search.fit(X_train, y_train)
end_time = time.time()

print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", bayes_search.best_params_)

# 使用最佳参数的模型进行预测
best_model = bayes_search.best_estimator_
best_pred = best_model.predict(X_test)

print("\n贝叶斯优化后的XGBoost 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("贝叶斯优化后的XGBoost 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))
from sklearn.metrics import accuracy_score
# --- 3. 贝叶斯优化LightGBM ---
print("\n--- 3. 贝叶斯优化LightGBM (训练集 -> 测试集) ---")
# 过滤 LightGBM 相关警告
warnings.filterwarnings("ignore", category=UserWarning, module="lightgbm")
# 定义要搜索的参数空间
search_space = {
    'n_estimators': (50, 500),
    'learning_rate': (0.01, 0.3),
    'max_depth': (3, 10),
    'num_leaves': (20, 200),
    'min_child_samples': (5, 50),
    'subsample': (0.5, 1.0),
    'colsample_bytree': (0.5, 1.0)
}

# 创建贝叶斯优化搜索对象
bayes_search = BayesSearchCV(
    estimator=lgb.LGBMClassifier(),
    search_spaces=search_space,
    n_iter=32,  # 迭代次数,可根据需要调整
    cv=5, # 5折交叉验证,这个参数是必须的,不能设置为1,否则就是在训练集上做预测了
    n_jobs=-1,
    scoring='accuracy'
)

start_time = time.time()
# 在训练集上进行贝叶斯优化搜索
bayes_search.fit(X_train, y_train)
end_time = time.time()

print(f"贝叶斯优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", bayes_search.best_params_)

# 使用最佳参数的模型进行预测
best_model = bayes_search.best_estimator_
best_pred = best_model.predict(X_test)

print("\n贝叶斯优化后的LightGBM 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("贝叶斯优化后的LightGBM 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))
# 计算并输出测试集上的准确率
test_accuracy = accuracy_score(y_test, best_pred)
print(f"贝叶斯优化后的LightGBM 在测试集上的准确率: {test_accuracy:.4f}")

选了3个模型进行训练,以精准度作为评判标准,最终是XGBoost的模型最好,所以用XGBoost进行预测。

预测和结果输出

# 提取特征,假设训练时使用的特征列都在 data2 中
# 你可能需要根据实际情况调整特征列名
if 'Cabin_T' not in data2.columns:
    data2['Cabin_T'] = 0

# 确保特征顺序和训练时一致
train_features = ['PassengerId', 'Pclass', 'Age', 'SibSp', 'Parch', 'Fare', 'Sex_female', 'Sex_male', 'Ticket_Bin_Low', 'Ticket_Bin_Medium', 'Ticket_Bin_High', 'Cabin_A', 'Cabin_B', 'Cabin_C', 'Cabin_D', 'Cabin_E', 'Cabin_F', 'Cabin_G', 'Cabin_NaN', 'Cabin_T', 'Embarked_C', 'Embarked_Q', 'Embarked_S']
X_pred = data2[train_features]


# 使用之前调好的 XGBoost 最佳模型进行预测
best_model = bayes_search.best_estimator_  # 这里使用贝叶斯优化得到的最佳模型
predictions = best_model.predict(X_pred)


# 将预测结果添加到一个新的 DataFrame 中
if 'PassengerId' in data2.columns:
    result_df = pd.DataFrame({
        'PassengerId': data2['PassengerId'],
        'Survived': predictions
    })
else:
    result_df = pd.DataFrame({
        'Survived': predictions
    })

# 将结果保存到 CSV 文件中
output_file_path = 'gender_submission.csv'
result_df.to_csv(output_file_path, index=False)

print(f"预测结果已保存到 {output_file_path}")

day 22_第1张图片

最终将结果上传到平台,分数0.75837

@浙大疏锦行

你可能感兴趣的:(60天计划,机器学习,人工智能)