Titanic船员获救问题是kaggle上一个很经典的机器学习练手项目,很适合机器学习入门阶段拿来练手以熟悉机器学习相关流程和知识。本篇文章用来记录本人学习TensorFlow时,用Titanic问题来练习的笔记。
通常机器学习的常规流程可概括为三部曲:
1.熟悉原始数据,并对原始数据进行预处理。比如对缺失值的处理、非数值型数据的处理等。
2.从预处理完的数据中挑选特征。挑选特征是机器学习的关键,模型训练的好坏和数据预处理以及特征挑选有很大关系。 因此发展出了特征工程这个领域,专门来“对付”特征挑选。
3.使用挑选好的特征来训练模型,并使用模型来预测测试集数据的结果。
根据以上流程,我使用TensorFlow分为六步来实现逻辑回归来预测Titanic船员获救数据。
1.数据读入及预处理
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
#读取训练数据
data = pd.read_csv("data/train.csv")
#查看数据情况
data.info()
#将Sex列数据转换为1或0
data['Sex'] = data['Sex'].apply(lambda s : 1 if s == 'male' else 0)
#缺失字段填充为0
data = data.fillna(0)
#选择以下特征用于分类
dataset_X = data[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare']]
dataset_X = dataset_X.as_matrix()
#两种分类分别是幸存和死亡,‘Survived’字段是其中一种分类的标签
#新增加'Deceased'字段表示第二种分类的标签,取值为'Survived'取非
data['Deceased'] = data['Survived'].apply(lambda s : int(not s))
dataset_Y = data[['Deceased', 'Survived']]
dataset_Y = dataset_Y.as_matrix()
#在训练数据中选择20%数据用来进行测试
X_train, X_val, y_train, y_val = train_test_split(dataset_X, dataset_Y, test_size=0.2, random_state=1)
2.构建计算图,采用逻辑回归进行构建
import tensorflow as tf
#声明输入数据占位符
#shape参数的第一个元素为None,表示可以同时放入任意条记录,每条记录都有6个特征
X = tf.placeholder(tf.float32, shape=[None, 6])
y = tf.placeholder(tf.float32, shape=[None, 2])
#声明参数变量权重W和bias
W = tf.Variable(tf.random_normal([6, 2]), name='weights')
bias = tf.Variable(tf.zeros([2]), name='bias')
#构造前向传播计算图
y_pred = tf.nn.softmax(tf.matmul(X, W) + bias)
#代价函数
cross_entropy = -tf.reduce_sum(y * tf.log(y_pred + 1e-10), reduction_indices=1)
cost = tf.reduce_mean(cross_entropy)
#加入优化算法:随机梯度下降算法
train_op = tf.train.GradientDescentOptimizer(0.001).minimize(cost)
3.构建训练迭代过程
with tf.Session() as sess:
tf.global_variables_initializer().run()
#以下为训练迭代,迭代100轮
for epoch in range(100):
total_loss = 0.
for i in range(len(X_train)):
feed = {X: [X_train[i]], y: [y_train[i]]}
#通过session.run接口触发执行
_, loss = sess.run([train_op, cost], feed_dict=feed)
total_loss += loss
print('Epoch: %04d, total loss=%.9f' % (epoch + 1, total_loss))
print('Training complete!')
#评估准确率
pred = sess.run(y_pred, feed_dict={X: X_val})
correct = np.equal(np.argmax(pred, 1), np.argmax(y_val, 1))
accuracy = np.mean(correct.astype(np.float32))
print("Accuracy on validation set: %.9f" % accuracy)
4.执行训练
执行训练的每个epoch结果如下:
Epoch: 0001, total loss=2978.986924756
Epoch: 0002, total loss=1233.613931798
Epoch: 0003, total loss=1433.674743123
Epoch: 0004, total loss=1425.632846644
Epoch: 0005, total loss=1413.414649527
Epoch: 0006, total loss=1401.179366778
Epoch: 0007, total loss=1389.302903898
Epoch: 0008, total loss=1377.886010977
.....
Epoch: 0099, total loss=1165.767331228
Epoch: 0100, total loss=1165.626431299
Training complete!
Accuracy on validation set: 0.687150836
通过以上执行结果可以看出100轮训练取得的准确率为0.687150836,我将epoch改为1000次后再执行,结果如下:
Epoch: 0001, total loss=1869.781745049
Epoch: 0002, total loss=1208.829884079
Epoch: 0003, total loss=1131.160947576
Epoch: 0004, total loss=1136.071243536
Epoch: 0005, total loss=1069.703441266
Epoch: 0006, total loss=1072.349545262
Epoch: 0007, total loss=1069.528637791
Epoch: 0008, total loss=1069.168335461
......
Epoch: 0999, total loss=970.790128045
Epoch: 1000, total loss=965.400083950
Training complete!
Accuracy on validation set: 0.770949721
由以上训练的epoch次数不同而最终准确率的不同,可以感受到训练次数对准确率的影响。
5.存储和加载模型参数
变量的存储和读取时通过tf.train.Saver类来完成的,Saver对象的save()方法用于存储,restore()方法用于读取。这里将变量保存在save目录下modle.ckpt中。
# 存档入口
saver = tf.train.Saver()
with tf.Session() as sess:
tf.global_variables_initializer().run()
#以下为训练迭代,迭代100轮
for epoch in range(100):
total_loss = 0.
for i in range(len(X_train)):
feed = {X: [X_train[i]], y: [y_train[i]]}
#通过session.run接口触发执行
_, loss = sess.run([train_op, cost], feed_dict=feed)
total_loss += loss
print('Epoch: %04d, total loss=%.9f' % (epoch + 1, total_loss))
print('Training complete!')
#评估准确率
pred = sess.run(y_pred, feed_dict={X: X_val})
correct = np.equal(np.argmax(pred, 1), np.argmax(y_val, 1))
accuracy = np.mean(correct.astype(np.float32))
print("Accuracy on validation set: %.9f" % accuracy)
#持久化存储变量
save_path = saver.save(sess, "save/model.ckpt")
6.使用模型对测试数据进行预测
Titanic问题是一个没有奖金的比赛项目,那么,训练出的模型就需要在给出的测试数据上来进行预测,并将预测结果一.cvs文件的形式上传kaggle网站。
#读入测试数据集并完成预处理,
testdata = pd.read_csv('data/test.csv')
testdata = testdata.fillna(0)
testdata['Sex'] = testdata['Sex'].apply(lambda s: 1 if s== 'male' else 0)
X_test = testdata[['Sex', 'Age', 'Pclass', 'SibSp', 'Parch', 'Fare']]
with tf.Session() as sess2:
tf.global_variables_initializer().run()
#加载模型存档
saver.restore(sess2, save_path)
#正向传播计算
predictions = np.argmax(sess2.run(y_pred, feed_dict={X:X_test}), 1)
#构建提交结果的数据结构,并将结果存储为csv文件
submission = pd.DataFrame({
"PassengerId": testdata["PassengerId"],
"Survived": predictions
})
#将预测数据写入titanic_submissioin.csv文件中
submission.to_csv("titanic_submission.csv", index=False)
代码和测试数据github路径:https://github.com/zhuwsh/Titanic-test/tree/master/data
本实验练习代码来自《深度学习原理与Tensorflow实践》