引言
泰坦尼克号电影中的很多场景大家可能还历历在目,这艘著名的英国豪华客轮在1912年4月15日航行的时候很不幸撞上了冰山而沉没,此次事故造成了大量人员的伤亡。而且这一事件引起了非常广泛的关注,也是历史上最触目惊心的海难之一。预测乘客的生还率成为了一个重要的问题。在本文中,我们将使用Python编程语言和调用Keras库,使用神经网络模型来预测泰坦尼克号上乘客的生还概率。
首先,我们要对泰坦尼克号人员的数据进行清洗,基于以下原因要对数据进行处理:
1、有些字段存在缺失
2、有些字段如性别是字符类型,机器学习中需要将字符类型数据转换为数值类型数据
3、有些字段存在多值情况,需要进行编码处理。
部分数据预览如下:
下面详细描述其步骤:
第一步:导入需要的库
import numpy;import pandas as pd
from sklearn import preprocessing
numpy.random.seed(10)
第二步:读取数据集
读取数据集文件,本文读取的是excel文件,并取字段‘survived','name','pclass' ,'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked’,其它对生还并不存在关联的字段就不采用。
all_df = pd.read_excel("titanic3.xls")
cols=['survived','name','pclass' ,'sex', 'age', 'sibsp',
'parch', 'fare', 'embarked']
all_df=all_df[cols]
第三步:划分数据集和测试集
#按照大约 80:20 的比例随机分配到了训练集和测试集中
msk = numpy.random.rand(len(all_df)) < 0.8
train_df = all_df[msk];test_df = all_df[~msk]
第四步:定义方法PreprocessData对数据进行处理
#对数据进行预处理:补缺失值,onehot编码转换,标准化归一化处理
def PreprocessData(raw_df):
df=raw_df.drop(['name'], axis=1)
age_mean = df['age'].mean()
df['age'] = df['age'].fillna(age_mean)
fare_mean = df['fare'].mean()
df['fare'] = df['fare'].fillna(fare_mean)
df['sex']= df['sex'].map({'female':0, 'male': 1}).astype(int)
x_OneHot_df = pd.get_dummies(data=df,columns=["embarked" ])
print("x_OneHot_df****:\n",x_OneHot_df)
ndarray = x_OneHot_df.values
Features = ndarray[:,1:]
Label = ndarray[:,0]
minmax_scale = preprocessing.MinMaxScaler(feature_range=(0, 1))
scaledFeatures=minmax_scale.fit_transform(Features)
print("scaledFeatures===\n",scaledFeatures)
return scaledFeatures,Label
第五步:调用上述定义的方法分别对训练集和测试集进行数据预处理
train_Features,train_Label=PreprocessData(train_df)
test_Features,test_Label=PreprocessData(test_df)
第六步:构建神经网络模型
我们将使用Keras库来构建神经网络模型。Keras是一个高级神经网络API,它简化了神经网络模型的构建和训练过程。
from keras.models import Sequential
from keras.layers import Dense,Dropout
model = Sequential()
model.add(Dense(units=80, input_dim=9,
kernel_initializer='uniform',
activation='relu'))
model.add(Dense(units=60,
kernel_initializer='uniform',
activation='relu'))
model.add(Dense(units=1,
kernel_initializer='uniform',
activation='sigmoid'))
print(model.summary())
第一个add方法:这行代码添加了一个全连接层到 Sequential 模型中。其中:
units=80 指定了该层的神经元数量为 80。
input_dim=9 指定了输入特征的维度为 9。
kernel_initializer='uniform' 表示初始化权重的方法为均匀分布。
activation='relu' 指定了该层的激活函数为 ReLU 函数。
第二个add方法:这行代码添加了第二个全连接层到 Sequential 模型中。参数的意义与前面的相似,但是不再需要指定输入特征的维度,因为在第一层已经指定过了。
第三个add方法:这行代码添加了最后一个全连接层到 Sequential 模型中,用于输出模型的预测结果。其中:
units=1 指定了输出层的神经元数量为 1,因为这是一个二分类问题。
activation='sigmoid' 指定了输出层的激活函数为 Sigmoid 函数,用于输出 0 到 1 之间的概率值。
第七步: 编译模型
model.compile(loss='binary_crossentropy',
optimizer='adam', metrics=['accuracy'])
在构建模型后,我们使用compile函数来编译模型。我们指定损失函数为二进制交叉熵,优化器为Adam,并选择准确度作为评估指标。
第八步:训练模型
# 训练模型
#将特征数据转换为float64
train_Features = train_Features.astype('float64')
#将标签数据转换为float64
train_Label = train_Label.astype('float64')
train_history =model.fit(x=train_Features,
y=train_Label,
validation_split=0.1,
epochs=30,
batch_size=30,verbose=2)
我们使用fit函数来训练模型。我们指定输入特征X和标签y,并选择训练的轮数和批次大小。Verbose=2表示显示训练过程。
注意:上述train_Features = train_Features.astype('float64')和train_Label = train_Label.astype('float64')两行代码是对数据类型进行转换,不转换会报错:
ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type int).
第九步:可视化训练过程的历史记录
#模型训练的结果均会保存在变量train_history中,所以通过访问该变量,可以使用图形的方式展示训练的过程。
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
def show_train_history(train_history, train, validation):
plt.plot(train_history.history[train])
plt.plot(train_history.history[validation])
plt.title('Train History')
plt.ylabel(train)
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
#输出训练和校验的准确率图
show_train_history(train_history, 'accuracy', 'val_accuracy')
#一共执行30个训练周期,无论是训练或验证,误差越来越小
show_train_history(train_history,'loss','val_loss')
第十步:评估模型
#训练完模型,现在使用测试集评估模型的准确率,准确率可以达到0.80
test_Features = test_Features.astype('float64')
test_Label = test_Label.astype('float64')
scores = model.evaluate(x=test_Features,
y=test_Label)
print(scores[1])
第十一步:准备新数据
#加入Jack & Rose数据,进行预测
Jack = pd.Series([0 ,'Jack',3, 'male' , 23, 1, 0, 5.0000,'S'])
Rose = pd.Series([1 ,'Rose',1, 'female', 20, 1, 0, 100.0000,'S'])
JR_df = pd.DataFrame([list(Jack),list(Rose)],
columns=['survived', 'name','pclass', 'sex',
'age', 'sibsp','parch', 'fare','embarked'])
all_df=pd.concat([all_df,JR_df])
all_df[-2:]
解释:
这段代码是用于创建两个新的数据条目,Jack 和 Rose,然后将它们添加到之前已有的 DataFrame `all_df` 中。
1. `Jack = pd.Series([0 ,'Jack',3, 'male' , 23, 1, 0, 5.0000,'S'])`:
这行代码创建了一个名为 Jack 的 Pandas Series 对象,其中包含了 Jack 的信息,依次为:生存情况(0 表示未生存)、姓名、船舱等级、性别、年龄、兄弟姐妹/配偶数量、父母/子女数量、票价、登船地点。
2. `Rose = pd.Series([1 ,'Rose',1, 'female', 20, 1, 0, 100.0000,'S'])`:
这行代码创建了一个名为 Rose 的 Pandas Series 对象,其中包含了 Rose 的信息,依次为:生存情况(1 表示生存)、姓名、船舱等级、性别、年龄、兄弟姐妹/配偶数量、父母/子女数量、票价、登船地点。
3. `JR_df = pd.DataFrame([list(Jack),list(Rose)], columns=['survived', 'name','pclass', 'sex', 'age', 'sibsp','parch', 'fare','embarked'])`:
这行代码创建了一个 DataFrame `JR_df`,其中包含了 Jack 和 Rose 的信息。使用 `pd.DataFrame()` 构造函数,将 Jack 和 Rose 的信息列表作为参数传递,并指定列名为 ['survived', 'name', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked']。
4. `all_df=pd.concat([all_df,JR_df])`:
这行代码使用 `pd.concat()` 函数将之前的 DataFrame `all_df` 与新创建的 DataFrame `JR_df` 连接起来,将它们堆叠在一起形成一个新的 DataFrame,并将其赋给了变量 `all_df`。
5. `all_df[-2:]`:
这行代码用于选择 DataFrame `all_df` 中的最后两行,即最新添加的 Jack 和 Rose 的信息。
这段代码的作用是创建了两个新的数据条目,并将它们添加到了原来的数据集 `all_df` 中,然后选择了新添加的最后两行以进行展示。
第十二步:用上述第十一步的新数据进行预处理
all_Features,Label=PreprocessData(all_df)
第十三步:对所有数据进行预测
#all_Features中包括新增的数据
all_probability=model.predict(all_Features)
第十四步:查看预测结果
all_probability[:10]
pd=all_df
pd.insert(len(all_df.columns),
'probability',all_probability)
#查看Jack & Rose数据的生存几率
pd[-2:]
第十五步:查看生存几率高,却没有存活
print(pd[(pd['survived']==0) & (pd['probability']>0.9) ])
第十六步:保存模型
try:
model.save('titanic_mlp_model.h5')
print('模型保存成功!,以后可以直接载入模型,不用再定义网络和编译模型!')
except:
print('模型保存失败!')
至此,采用Keras库实现泰坦尼克号上人员生还预测模型的构建、训练、预测、评估、保存模型等就全部完成。该实验使用到的数据可以在我博客中的下载中找到。