5-8以前为tensorflow2.0 ,5-8以后为tensorflow1.0
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pandas as pd
import os
import sys
import time
import sklearn
from tensorflow import keras
import tensorflow as tf
print(tf.__version__)
print(sys.version_info)
for module in mpl, np, pd, sklearn, tf, keras:
print(module.__name__, module.__version__)
# 泰坦尼克数据集含义 = {'survived':'预测的值,有无获救', 'sex', 'age', 'n_siblings_spouses':'兄弟姐妹及配偶的人数', 'parch':'父母及孩子人数', 'fare':'船票费用','class':'仓位(高等/中等/低等)', 'deck':'船舱的位置', 'embark_town':'从哪个港口出发', 'alone':'是否独自一人'}
train_df = pd.read_csv('train.csv')
eval_df = pd.read_csv('eval.csv')
y_train = train_df.pop('survived')
y_eval = eval_df.pop('survived')
train_df.head(3)
categorical_columns = ['sex', 'parch', 'n_siblings_spouses', 'class', 'deck', 'embark_town', 'alone'] # 离散特征
numeric_columns = ['age', 'fare'] # 连续特征
feature_columns = []
for categorical_column in categorical_columns:
vocab = train_df[categorical_column].unique()
print(categorical_column, vocab)
feature_columns.append(
tf.feature_column.indicator_column(
tf.feature_column.categorical_column_with_vocabulary_list(categorical_column, vocab)))
for numeric_column in numeric_columns:
feature_columns.append(
tf.feature_column.numeric_column(numeric_column, dtype=tf.float32))
def make_dataset(data_df, label_df, epochs=10, shuffle=True, batch_size=32):
dataset = tf.data.Dataset.from_tensor_slices( (train_df.to_dict('list'), label_df))
if shuffle :
dataset = dataset.shuffle(10000)
dataset = dataset.repeat(epochs).batch(batch_size)
return dataset
train_dataset = make_dataset(train_df, y_train, batch_size=)
for x,y in train_dataset.take(1):
print(keras.layers.DenseFeatures(feature_columns)(x).numpy())
# 13.8625是fare特征,在5.3.2中直接tf.feature_column.numeric_column,无需进行one_hot编码映射,在原始数据查找只有一条记录
train_df[train_df['fare'] == 13.8625]
# 使用pprint查看特征的先后顺序为['age','alone','class','deck','embark_town','fare','n_siblings_spouses','parch','sex']
import pprint
for x,y in train_dataset.take(1):
pprint.pprint(x)
model = keras.models.Sequential([
keras.layers.DenseFeatures(feature_columns),
keras.layers.Dense(100, activation='relu'),
keras.layers.Dense(100, activation='relu'),
keras.layers.Dense(2, activation='softmax')
])
model.compile(loss='sparse_categorical_crossentropy',
optimizer=keras.optimizers.SGD(lr=0.01),
metrics = ['accuracy'])
train_dataset = make_dataset(train_df, train_df, epochs=100) # 当train_df为数值型时用sparse_categorical_crossentropy,他会将train_df先转成one-hot编码,是one-hot编码时用categorical_crossentropy
eval_dataset = make_dataset(eval_df, y_eval, epochs=1, shuffle=False)
history = model.fit(train_dataset, validation_data=eval_dataset,
steps_per_epoch = len(train_df)//32,
validation_steps = len(eval_df) // 32,
epochs = 100)
estimator = keras.estimator.model_to_estimator(model)
estimator.train(input_fn = lambda: make_dataset(train_df, y_train, epochs=100)) # 该版本有错误,应该是对那些转为feature的数据集的数据不兼容
# input_fn的函数必须返回(features, label)元祖,但不能有参数
output_dir = 'baseline_model'
if not os.path.exists(output_dir):
os.mkdir(output_dir)
baseline_estimator = tf.compat.v1.estimator.BaselineClassifier(model_dir=output_dir,n_classes=2)
baseline_estimator.train(input_fn = lambda : make_dataset(train_df, y_train, epochs=100))
# baseline_estimator.train( input_fn = fun('t') )
baseline_estimator.evaluate(input_fn=lambda : make_dataset(eval_df, y_eval, epochs=1, shuffle=False, batch_size=20))
linear_output_dir = 'linear_model'
if not os.path.exists(linear_output_dir):
os.mkdir(linear_output_dir)
linear_estimator = tf.estimator.LinearClassifier(model_dir=linear_output_dir,
n_classes=2,
feature_columns=feature_columns)
linear_estimator.train(input_fn = lambda : make_dataset(train_df, y_train, epochs=100))
linear_estimator.evaluate(input_fn=lambda :make_dataset(eval_df, y_eval, epochs=1, shuffle=False))
dnn_output_dir = 'dnn_model'
if not os.path.exists(dnn_output_dir):
os.mkdir(dnn_output_dir)
dnn_estimator = tf.estimator.DNNClassifier(model_dir=dnn_output_dir,
n_classes=2,
feature_columns=feature_columns,
hidden_units = [128,128],
activation_fn=tf.nn.relu,
optimizer='Adam')
dnn_estimator.train(input_fn = lambda : make_dataset(train_df, y_train, epochs=100))
dnn_estimator.evaluate(input_fn=lambda :make_dataset(eval_df, y_eval, epochs=1, shuffle=False))
# 离散和连续特征分类构建用于后续的映射
categorical_columns = ['sex', 'parch', 'n_siblings_spouses', 'class', 'deck', 'embark_town', 'alone'] # 离散特征
numeric_columns = ['age', 'fare'] # 连续特征
feature_columns = []
for categorical_column in categorical_columns:
vocab = train_df[categorical_column].unique()
print(categorical_column, vocab)
feature_columns.append(
tf.feature_column.indicator_column(
tf.feature_column.categorical_column_with_vocabulary_list(categorical_column, vocab)))
for numeric_column in numeric_columns:
feature_columns.append(
tf.feature_column.numeric_column(numeric_column, dtype=tf.float32))
# 添加交叉特征
# age : [1,2,3] gender = ['male', 'female']
# 生成交叉特征 : [(1.'male'), (1,'female'), ..., (3,'female')]
# hash_bucket_size 作用,因为交叉特征的量可能太多,比如2个原始特征size=100,那么交叉特征的size=10000个,作为输入
# 太大,需要进行减少 ,减少过程 hash(10000 value) % 100, 这样每次使用的交叉特征就只有100个
feature_columns.append(
tf.feature_column.indicator_column(
tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)))
下面再用BaselineClassifier,LinearClassifier,DNNClassifier进行训练,训练过程和5.5一致。
为什么使用交叉特征: 在wide&deep模型中,离散特征使用交叉特征能更细节的记住一个人
结论: 发现dnn模型增加了交叉特征后,accuracy还降低了,base方法没变化,linear方法升高,说明增加交叉特征
对提升每个模型的作用不同。如果想在dnn模型中使用交叉特征,那就需要使用wide&deep模型,因为单纯加入只会
减少精确率
fashion_mnist = keras.datasets.fashion_mnist
(x_train_all, y_train_all),(x_test, y_test) = fashion_mnist.load_data()
x_valid, x_train = x_train_all[:5000], x_train_all[5000:]
y_valid, y_train = y_train_all[:5000], y_train_all[5000:]
# 数据归一化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
x_train_scaled = scaler.fit_transform(
x_train.astype(np.float32).reshape(-1,1)).reshape(-1, 28 * 28)
x_valid_scaled = scaler.transform(
x_valid.astype(np.float32).reshape(-1,1)).reshape(-1, 28 * 28)
x_test_scaled = scaler.transform(
x_test.astype(np.float32).reshape(-1,1)).reshape(-1, 28 * 28)
x_train_scaled.shape, y_train.shape
((55000, 784), (55000,))
hidden_units = [100, 100]
class_num = 10
x = tf.placeholder(tf.float32, [None, 28 * 28]) # None代表batch_size的大小,可以输入任意值
y = tf.placeholder(tf.int64, [None]) # None代表batch_size大小,不知道batch_size多少,先占位
# 开始构建网络层
# 输出层到隐藏层构建
input_for_next_layer = x
for hidden_unit in hidden_units:
Input_for_next_layer = tf.layers.dense(input_for_next_layer, hidden_unit, activation=tf.nn.relu)
# logits: 最后一层输出,还没用激活函数
logits = tf.layers.dense(input_for_next_layer, class_num)
# loss: 1. 使用softmax将logits转换为概率prob ; 2. labels -> one_hot;3. 计算交叉熵corss_entropy损失函数
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=logits) # 将labels转成one_hot编码
# 过去accuracy
prediction = tf.argmax(logits, axis=1) # 求出每一行的最大值对应的索引,若logits为1位数组如[1,2,3],那么axis只能等于0,
# 因为一维数组默认是认为列,这里的logits是二维
correct_predition = tf.equal(prediction, y)
accuracy = tf.reduce_mean(tf.cast(correct_predition, tf.float64))
train_op = tf.train.AdamOptimizer(1e-3).minimize(loss) # 1e-3为learning_rate
init = tf.global_variables_initializer()
batch_size = 20
epochs = 10
train_steps_for_epoch = len(x_train_scaled) // batch_size
def eval_with_sess(sess, x, y, accuracy, images, labels, batch_size):
eval_steps = len(images) // batch_size
eval_accuracies = []
for step in range(eval_steps):
batch_data = images[step*batch_size: (step+1)*batch_size]
batch_label = labels[step*batch_size: (step+1)*batch_size]
accuracy_val = sess.run(accuracy, feed_dict={
x: batch_data,
y: batch_label
})
eval_accuracies.append(accuracy_val)
return np.mean(eval_accuracies)
with tf.Session() as sess:
sess.run(init)
for epoch in range(epochs):
for step in range(train_steps_for_epoch):
batch_data = x_train_scaled[step*batch_size: (step+1)*batch_size]
batch_label = y_train[step*batch_size: (step+1)*batch_size]
loss_val, accuracy_val, _ = sess.run(
[loss, accuracy, train_op], feed_dict = {
x: batch_data,
y: batch_label
})
print("\r [Train] epoch: %d, step: %d , loss: %3.5f , accuracy %3.5f" %
(epoch, step, loss_val, accuracy_val), end="") # mac下\r与换行符\r冲突
valid_accuracy = eval_with_sess(sess, x, y, accuracy, x_valid_scaled, y_valid, batch_size)
print("\t[Valid] acc : %2.2f " % (valid_accuracy) )
# 避免后面类型错误
y_train = np.asarray(y_train, dtype=np.int64)
y_valid = np.asarray(y_valid, dtype=np.int64)
y_test = np.asarray(y_test, dtype=np.int64)
def make_dataset(images, labels, epochs, batch_size, shuffle=True):
dataset = tf.data.Dataset.from_tensor_slices((images, labels))
if shuffle :
dataset = dataset.shuffle(10000)
dataset = dataset.repeat(epochs).batch(batch_size)
return dataset
batch_size = 20
epochs = 10
hidden_units = [100, 100]
class_num = 10
# make_one_shot_iterator
# 1. 自动初始化 2. 不能被重新初始化 make_initializable_interator能重新初始化加载训练集验证集数据
dataset = make_dataset(x_train_scaled, y_train, epochs, batch_size)
dataset_iter = dataset.make_one_shot_iterator()
x, y = dataset_iter.get_next()
# x = tf.placeholder(tf.float32, [None, 28 * 28]) # x,y 已经生成
# y = tf.placeholder(tf.int64, [None])
input_for_next_layer = x
for hidden_unit in hidden_units:
Input_for_next_layer = tf.layers.dense(input_for_next_layer, hidden_unit, activation=tf.nn.relu)
logits = tf.layers.dense(input_for_next_layer, class_num)
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=logits)
prediction = tf.argmax(logits, axis=1)
correct_predition = tf.equal(prediction, y)
accuracy = tf.reduce_mean(tf.cast(correct_predition, tf.float64))
train_op = tf.train.AdamOptimizer(1e-3).minimize(loss) # 1e-3为learning_rate
init = tf.global_variables_initializer()
train_steps_per_epoch = len(x_train_scaled) // batch_size
with tf.Session() as sess:
sess.run(init)
for epoch in range(epochs):
for step in range(train_steps_per_epoch):
loss_val, accuracy_val, _ = sess.run( [loss, accuracy, train_op])
print("\r [Train] epoch: %d, step: %d , loss: %3.5f , accuracy %3.5f" %
(epoch, step, loss_val, accuracy_val), end="") # mac下\r与换行符\r冲突
print()
epochs = 10
batch_size = 128
images_placeholder = tf.placeholder(tf.float32, [None, 28*28])
labels_placeholder = tf.placeholder(tf.int64, (None,))
dataset = make_dataset(images_placeholder, labels_placeholder, epochs=10, batch_size=batch_size)
dataset_iter = dataset.make_initializable_iterator()
x, y = dataset_iter.get_next()
hidden_units = [100, 100]
class_num = 10
input_for_next_layer = x
for hidden_unit in hidden_units:
Input_for_next_layer = tf.layers.dense(input_for_next_layer, hidden_unit, activation=tf.nn.relu)
logits = tf.layers.dense(input_for_next_layer, class_num)
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=logits)
prediction = tf.argmax(logits, axis=1)
correct_predition = tf.equal(prediction, y)
accuracy = tf.reduce_mean(tf.cast(correct_predition, tf.float64))
train_op = tf.train.AdamOptimizer(1e-3).minimize(loss) # 1e-3为learning_rate
init = tf.global_variables_initializer()
train_steps_per_epoch = len(x_train_scaled) // batch_size
valid_steps = len(x_valid_scaled) // batch_size
def eval_with_sess(sess, images, labels ):
sess.run(dataset_iter.initializer, feed_dict={
images_placeholder: images,
labels_placeholder: labels,
})
return np.mean([sess.run(accuracy) for step in range(valid_steps)])
with tf.Session() as sess:
sess.run(init)
for epoch in range(epochs):
sess.run(dataset_iter.initializer, feed_dict={
images_placeholder: x_train_scaled,
labels_placeholder: y_train
})
for step in range(train_steps_per_epoch):
loss_val, accuracy_val, _ = sess.run([loss, accuracy, train_op])
print("\r [Train] epoch: %d, step: %d , loss: %3.5f , accuracy %3.5f" %
(epoch, step, loss_val, accuracy_val), end="") # mac下\r与换行符\r冲突
valid_accuracy = eval_with_sess(sess, x_valid_scaled, y_valid)
print("\t valid acc: %3.5f"% valid_accuracy)
train_df = pd.read_csv('train.csv')
eval_df = pd.read_csv('eval.csv')
y_train = train_df.pop('survived')
y_eval = eval_df.pop('survived')
train_df.head(3)
# 离散和连续特征分类构建用于后续的映射
categorical_columns = ['sex', 'parch', 'n_siblings_spouses', 'class', 'deck', 'embark_town', 'alone'] # 离散特征
numeric_columns = ['age', 'fare'] # 连续特征
feature_columns = []
for categorical_column in categorical_columns:
vocab = train_df[categorical_column].unique()
print(categorical_column, vocab)
feature_columns.append(
tf.feature_column.indicator_column(
tf.feature_column.categorical_column_with_vocabulary_list(categorical_column, vocab)))
for numeric_column in numeric_columns:
feature_columns.append(
tf.feature_column.numeric_column(numeric_column, dtype=tf.float32))
# 构建数据集
def make_dataset(data_df, label_df, epochs=10, shuffle=True, batch_size=32):
dataset = tf.data.Dataset.from_tensor_slices( (data_df.to_dict('list'), label_df))
if shuffle :
dataset = dataset.shuffle(10000)
dataset = dataset.repeat(epochs).batch(batch_size)
return dataset.make_one_shot_iterator().get_next()
def model_fn(features, labels, mode, params):
# model 运行状态 PREDICT, EVAL,TRAIN
input_for_next_layer = tf.feature_column.input_layer(
features, params['feature_columns'])
for n_unit in params['hidden_units']:
input_for_next_layer = tf.layers.dense(input_for_next_layer, units=n_unit, activation=tf.nn.relu)
logits = tf.layers.dense(input_for_next_layer, params['n_classes'], activation=None)
predicted_classes = tf.argmax(logits, 1)
if mode == tf.estimator.ModeKeys.PREDICT:
pretictions = {
"class_ids": predicted_classes[:, tf.newaxis],
"probabilities": tf.nn.softmax(logits),
"logits": logits
}
return tf.estimator.EstimatorSpec(mode, predictions=pretictions)
loss= tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
accuracy = tf.metrics.accuracy(labels=labels, predictions= predicted_classes, name='acc_op') # 这里的accuracy会累积,不用手写求和后求平均
metrics = {"accuracy": accuracy}
if mode == tf.estimator.ModeKeys.EVAL:
return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)
optimizer = tf.train.AdamOptimizer() # 在梯度下降时自适应调整learning_rate,不会导致梯度很大时的学习步长太大,性能差表现好,表现好:不太会发散
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
if mode == tf.estimator.ModeKeys.TRAIN:
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
output_dir = "tf_1.0_customized_estimator"
if not os.path.isdir(output_dir): os.mkdir(output_dir)
estimator = tf.estimator.Estimator(
model_fn = model_fn,
model_dir= output_dir,
params = {
"feature_columns": feature_columns,
"hidden_units": [100, 100],
"n_classes": 2
}
)
estimator.train(input_fn = lambda: make_dataset(train_df, y_train, epochs=100))
estimator.evaluate(lambda : make_dataset(eval_df, y_eval, epochs=1))