数据:titanic3.xls
处理数据
首先要把 xls 文件中的数据读进来,使用 pandas 库的 read_excel():
import pandas as pd
import numpy as np
all_data = pd.read_excel('titanic3.xls')
读进来的数据可以用 all_data[:2]
查看前两行
列名 | 含义 |
---|---|
PassengerId | 乘客编号 |
Survival | 是否生还,0表示未生还,1表示生还 |
Pclass | 船票种类,1表示上层,2表示中层,3表示底层 |
Sex | 性别,男性为male,女性为female |
Age | 年龄,不满1岁的年龄为小数 |
SibSp | 该乘客同船的兄弟姐妹及配偶的数量 |
Parch | 该乘客同船的父母以及儿女的数量 |
Ticket | 船票编号 |
Fare | 买票的费用 |
Cabin | 船舱编号 |
Embarked | 代表在哪里上的船 |
有些东西不会影响生还率,比如:姓名、船票编号、船舱编号、在哪里上船等,但是要用姓名来进行预测,所以要保留,而在哪里上船(embarked)也暂时保留,用它学个新知识,正常训练删掉就可
可以先把要保留的字段做成一个列表,然后再把列表保留出来
cols = ['survived', 'name', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'embarked']
#cols = ['survived', 'name', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare']
all_data = all_data[cols]
embarked 这个列是字母,把它换成一位有效编码,用的是 get_dummies 这个方法
OneHot_data = pd.get_dummies(data=data_train, columns=['embarked'])
正式处理数据:
我们取 80% 作为训练数据,剩下的作为测试数据
msk = np.random.random(len(all_df)) < 0.8
train_data = all_data[msk]
test_data = all_data[~msk]
写一个函数综合处理一下:
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})
ndarray = df.values
Label = ndarray[:, 0]
Features = ndarray[:, 1:]
minmax_scale = preprocessing.MinMaxScaler((0,1))
scaledFeatures = minmax_scale.fit_transform(Features)
return scaledFeatures, Label
下面一个一个介绍是干啥的:
因为 name 列对于训练是没用的,只是后面拿来预测用,所以先把 name 列去除
df = raw_df.drop(['name'], axis = 1)
有个问题,有些列中存在空值,我们可以看一下有多少
data_train.isnull().sum()
对于这些存在空值的列,可以把他们填充为这一列的平均值,mean()
就是取平均值
age_mean = df['age'].mean()
df['age'] = df['age'].fillna(age_mean)
fare_mean = df['fare'].mean()
df['fare'] = df['fare'].fillna(fare_mean)
对于性别这一列,使用 map 方法,将 female 设置为 0,male 设置为 1
df['sex'] = df['sex'].map({'female':0, 'male':1})
再把数据转换为数组
ndarray = df.values
取第一列的数据作为标签 Label,剩下的是特征 Features
Label = ndarray[:, 0]
Features = ndarray[:, 1:]
接下来把数据进行归一化,但是这里的数据跟图片的数据不一样了,他不是一定落在 0-255 之间,所以没法直接除 255,MinMaxScaler()
方法用于产生标准化刻度,参数设置为(0~1),表示将数据标准化后全部落在 0~1 之间的一个刻度工具
minmax_scale = preprocessing.MinMaxScaler((0,1))
scaledFeatures = minmax_scale.fit_transform(Features)
实际处理数据的时候就:
train_Features,train_Label = PreprocessData(train_data)
test_Features,test_Label = PreprocessData(test_data)
创建模型
from keras.models import Sequential
from keras.layers import Dense, Dropout
model = Sequential()
model.add(Dense(units = 200, input_dim=6, kernel_initializer='uniform', activation='relu'))
model.add(Dense(units = 200, kernel_initializer='uniform', activation='relu'))
model.add(Dense(units=1, kernel_initializer='uniform', activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
训练
train_history = model.fit(train_Feature, train_Label, validation_split=0.2, epochs=50, batch_size=20, verbose=2)
验证模型准确率
scores = model.evaluate(test_Feature, test_Label)
print(scores)
添加人物信息
把想要预测的任务构建出来
比如想要预测 yichen:
#'survived:是否生还', 'name', 'pclass:船票种类(1>2>3)', 'sex', 'age', 'sibsp:兄弟姐妹数', 'parch:父母孩子数', 'fare:买票的费用'
yichen_data = [1,'yichen','3','male',22,0,2,32.7]
是否生还这一项,预测的时候就不用了,无关紧要,但我还是写成了生还哈哈哈哈哈
我这肯定是最底层的船舱了,费用就取了个他们的平均数 32.7
yichen_df = pd.DataFrame([list(yichen_data)], columns=['survived', 'name', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare'])
然后用写好的函数处理一下
yichen_Features,label = PreprocessData(yichen_df)
预测一下
probability = model.predict(yichen_Features)
看看结果
yichen_df.insert(len(yichen_df.columns), 'probability', probability)
我这生还率高得离谱!?
呸,不能这样算!!!!
它是按照那么多人有几个小艇可以走那样训练的,就一个人必存活呀
先把这个数据加在总的数据里面,这样生还率应该稍微比真实情况偏低一丁点,但是这样才是预测的正确姿势呀
all_df = pd.concat([all_df, yichen_df])
呜呜呜,29% 的生还率
要是能买个 1 等的船舱就是 71% 啦
为啥花的钱少生存率还能高啊?