前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TensorFlow 基础实战

TensorFlow 基础实战

作者头像
周萝卜
发布2019-07-17 16:10:44
8410
发布2019-07-17 16:10:44
举报

今天通过一个实例,来学习下 Tensorflow 的基本操作加实战

初识 Tensorflow

Tensorflow 是干嘛的,就不过多赘述了,小伙伴们可以访问官网来详细了解 https://www.tensorflow.org/

基础概念

•    张量 •    指令 •    图 •    会话

张量:张量是任意维度的数组

标量,是零维数组(零阶张量)。例如,\'Howdy\' 或 5 矢量,是一维数组(一阶张量)。例如,[2, 3, 5, 7, 11] 或 [5] 矩阵,是二维数组(二阶张量)。例如,[[3.1, 8.2, 5.9][4.3, -2.7, 6.5]]

指令:指令会创建、销毁和控制张量

大多数 Tensorflow 代码都是指令。

图(也称为计算图或数据流图):是一种图数据结构

图的节点是指令,图的边是张量。张量流经图,在每个节点由一个指令操控。一个指令的输出张量通常会变成后续指令的输入张量。 张量可以作为常量或者变量存储在图中。常量是始终会返回同一张量值的指令。变量是会返回分配给它的任何张量的指令。

定义常量:

x = tf.constant([5.2])

定义变量:

y = tf.Variable([5])

给变量赋值:

y = tf.Variable([0])
y = y.assign([5])

会话:图必须运行在会话中

会话存储了它所运行图的状态。

with tf.Session() as sess:
  initialization = tf.global_variables_initializer()
  print(y.eval())

Tensorflow 编程总结:

  1. 将常量、变量和指令整合到一个图中。
  2. 在一个会话中评估这些常量、变量和指令。

实战房价预测

因为搭建 Tensorflow 环境还是蛮复杂的,这里还是使用 Google Colab 环境。

加载必要库

import math
# display模块可以决定显示的内容以何种格式显示
from IPython import display
# matplotlib为python的2D绘图库
# cm为颜色映射表
from matplotlib import cm  
# 使用 GridSpec 自定义子图位置
from matplotlib import gridspec
# pyplot提供了和matlab类似的绘图API,方便用户快速绘制2D图表
from matplotlib import pyplot as plt
# numpy为python的科学计算包,提供了许多高级的数值编程工具
import numpy as np    
# pandas是基于numpy的数据分析包,是为了解决数据分析任务而创建的    
import pandas as pd     
# sklearn(scikit-_learn_)是一个机器学习算法库,包含了许多种机器学习得方式
# *   Classification 分类
# *   Regression 回归
# *   Clustering 非监督分类
# *   Dimensionality reduction 数据降维
# *   Model Selection 模型选择
# *   Preprocessing 数据预处理 
# metrics:度量(字面意思),它提供了很多模块可以为第三方库或者应用提供辅助统计信息
from sklearn import metrics
# tensorflow是谷歌的机器学习框架
import tensorflow as tf   
# Dataset无比强大得数据集
from tensorflow.python.data import Dataset

tf.logging.set_verbosity(tf.logging.ERROR)
# 为了观察数据方便,最多只显示10行数据
pd.options.display.max_rows = 10
pd.options.display.float_format = '{:.1f}'.format

加载数据集

数据基于加利福尼亚州 1990 年的人口普查数据。

housing_dataframe = pd.read_csv("https://download.mlcc.google.cn/mledu-datasets/california_housing_train.csv", sep=",")
housing_dataframe.describe()

随机排序数据,因为这样更接近生活中的真实数据,并将 median_house_value 的数值以千为单位处理,同时查看数据概要信息。

housing_dataframe = housing_dataframe.reindex(
    np.random.permutation(housing_dataframe.index))
housing_dataframe["median_house_value"] /= 1000.0
housing_dataframe.describe()

构建模型

因为是准备预测 median_house_value 的值,所以它就是我们的标签(也成为目标)。因为 total_rooms 代表的是某个街区的总房数,所以用 total_rooms 作为输入特征。 这里选取 TensorFlow Estimator API(是基于 Tensorflow 的高级 API) 提供的 LinearRegressor 接口,来构建模型。

1. 定义特征并配置特征列

我们要指定每个特征所包含的数据类型,根据经验,主要有两种数据类型: 分类数据:一种文字数据。 数值数据:一种数字(整数或者浮点数)数据以及可以视为数字的数据。

在 TensorFlow 中,使用一种称为“特征列”的结构来表示特征的数据类型。特征列仅仅存储对特征数据的描述,不包含特征数据本身。

提取特征total_rooms数据,并使用 numeric_column定义特征列,将其数据指定为数值数据。

# Define the input feature: total_rooms.
my_feature = housing_dataframe[["total_rooms"]]

# Configure a numeric feature column for total_rooms.
feature_columns = [tf.feature_column.numeric_column("total_rooms")]

2. 定义标签

从 housing_dataframe 中提取标签

# Define the label.
targets = housing_dataframe["median_house_value"]

3. 创建回归模型

使用 LinearRegressor 配置线性回归模型,并通过 GradientDescentOptimizer(它会实现小批量随机梯度下降法 (SGD))训练该模型。learning_rate 参数可控制梯度步长的大小。 为了安全起见,我们还会通过 clip_gradients_by_norm 将梯度裁剪应用到优化器。梯度裁剪可确保梯度大小在训练期间不会变得过大,梯度过大会导致梯度下降法失败。

# Use gradient descent as the optimizer for training the model.
my_optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.0000001)
my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)

# Configure the linear regression model with our feature columns and optimizer.
# Set a learning rate of 0.0000001 for Gradient Descent.
linear_regressor = tf.estimator.LinearRegressor(
    feature_columns=feature_columns,
    optimizer=my_optimizer
)

梯度 (gradient):偏导数相对于所有自变量的向量。在机器学习中,梯度是模型函数偏导数的向量。梯度指向最速上升的方向。 梯度下降法 (gradient descent):一种通过计算并且减小梯度将损失降至最低的技术,它以训练数据为条件,来计算损失相对于模型参数的梯度。通俗来说,梯度下降法以迭代方式调整参数,逐渐找到权重和偏差的最佳组合,从而将损失降至最低。

这里还涉及了一些其他的机器学习的概念,比如学习速率,梯度裁剪等,感兴趣的同学可以自行查找概念。

4. 定义导入数据函数

主要定义TensorFlow 如何对数据进行预处理,以及在模型训练期间如何批处理、随机处理和重复数据。

  1. 首先,将 Pandas 特征数据转换成 NumPy 数据字典。然后,使用 TensorFlow Dataset API 构建 Dataset 对象,并将数据拆分成大小为 batch_size 的多批次数据,以此来按照指定周期(num_epochs)进行重复。 如果 num_epochs 设置为 None,那么输入的数据会无限期重复训练。
  2. 其次,可以设置 shuffle 为 True,来对数据进行随机处理,以便数据在训练期间以随机的方式传递到模型。buffer_size 参数会指定 shuffle 将从中随机抽样的数据集的大小。
  3. 最后,我们定义的输入函数,可以为数据集构建一个迭代器,并向模型返回下一批数据。
def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
    # Convert pandas data into a dict of np arrays.
    features = {key:np.array(value) for key,value in dict(features).items()}                                           

    # Construct a dataset, and configure batching/repeating.
    ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit
    ds = ds.batch(batch_size).repeat(num_epochs)

    # Shuffle the data, if specified.
    if shuffle:
      ds = ds.shuffle(buffer_size=10000)

    # Return the next batch of data.
    features, labels = ds.make_one_shot_iterator().get_next()
return features, labels

有关 Dataset API 更详细的文档,请参阅 TensorFlow 编程人员指南.

5. 训练模型

现在再在 linear_regressor 上调用 train() 来训练模型。

_ = linear_regressor.train(
    input_fn = lambda:my_input_fn(my_feature, targets),
    steps=100
)

这里使用 _ 来接收函数,目的是表明函数是有返回值的,但是我们并不需要返回值。

6. 评估模型

我们基于该训练数据做一次预测,看看我们的模型在训练期间与这些数据的拟合情况。 训练误差可以衡量我们的模型与训练数据的拟合情况,但并不能衡量模型泛化到新数据的效果。

泛化能力(generalization ability)是指机器学习算法对新鲜样本的适应能力。学习的目的是学到隐含在数据对背后的规律,对具有同一规律的学习集以外的数据,经过训练的网络也能给出合适的输出,该能力称为泛化能力。

# Create an input function for predictions.
# Note: Since we're making just one prediction for each example, we don't 
# need to repeat or shuffle the data here.
prediction_input_fn =lambda: my_input_fn(my_feature, targets, num_epochs=1, shuffle=False)

# Call predict() on the linear_regressor to make predictions.
predictions = linear_regressor.predict(input_fn=prediction_input_fn)

# Format predictions as a NumPy array, so we can calculate error metrics.
predictions = np.array([item['predictions'][0] for item in predictions])

# Print Mean Squared Error and Root Mean Squared Error.
mean_squared_error = metrics.mean_squared_error(predictions, targets)
root_mean_squared_error = math.sqrt(mean_squared_error)
print("Mean Squared Error (on training data): %0.3f" % mean_squared_error)
print("Root Mean Squared Error (on training data): %0.3f" % root_mean_squared_error)

得到的结果如下: (均方误差)Mean Squared Error (on training data): 56425052440.760 (均方根误差)Root Mean Squared Error (on training data): 237539.581 我们通常使用均方根误差来判断误差的大小,因为它通常会与 target 在同一个数量级上。 比较一下 RMSE 与目标最大值和最小值的差值

min_house_value = housing_dataframe["median_house_value"].min()
max_house_value = housing_dataframe["median_house_value"].max()
min_max_difference = max_house_value - min_house_value

print("Min. Median House Value: %0.3f" % min_house_value)
print("Max. Median House Value: %0.3f" % max_house_value)
print("Difference between Min. and Max.: %0.3f" % min_max_difference)
print("Root Mean Squared Error: %0.3f" % root_mean_squared_error)

结果:

Min. Median House Value: 14999.000 Max. Median House Value: 500001.000 Difference between Min. and Max.: 485002.000 Root Mean Squared Error: 237539.581

再根据总体摘要统计信息,了解预测和目标的符合情况

calibration_data = pd.DataFrame()
calibration_data["predictions"] = pd.Series(predictions)
calibration_data["targets"] = pd.Series(targets)
calibration_data.describe()

很明显,预测的结果并不好,我们要继续调整参数,增加训练时长,来获得更好的模型。

7. 超参数调整

定义一个可以自由调整参数的函数,来方便的调节超参,并绘制出训练数据

def train_model(learning_rate, steps, batch_size, input_feature="total_rooms"):
  periods = 10
  steps_per_period = steps / periods

  my_feature = input_feature
  my_feature_data = california_housing_dataframe[[my_feature]]
  my_label = "median_house_value"
  targets = california_housing_dataframe[my_label]

  # Create feature columns.
  feature_columns = [tf.feature_column.numeric_column(my_feature)]

  # Create input functions.
  training_input_fn = lambda:my_input_fn(my_feature_data, targets, batch_size=batch_size)
  prediction_input_fn = lambda: my_input_fn(my_feature_data, targets, num_epochs=1, shuffle=False)

  # Create a linear regressor object.
  my_optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
  my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
  linear_regressor = tf.estimator.LinearRegressor(
      feature_columns=feature_columns,
      optimizer=my_optimizer,
      config=tf.estimator.RunConfig(model_dir='out')
  )

  # Set up to plot the state of our model's line each period.
  plt.figure(figsize=(15, 6))
  plt.subplot(1, 2, 1)
  plt.title("Learned Line by Period")
  plt.ylabel(my_label)
  plt.xlabel(my_feature)
  sample = california_housing_dataframe.sample(n=300)
  plt.scatter(sample[my_feature], sample[my_label])
  colors = [cm.coolwarm(x) for x in np.linspace(-1, 1, periods)]

  # Train the model, but do so inside a loop so that we can periodically assess
  # loss metrics.
  print("Training model...")
  print("RMSE (on training data):")
  root_mean_squared_errors = []
  for period in range (0, periods):
    # Train the model, starting from the prior state.
    linear_regressor.train(
        input_fn=training_input_fn,
        steps=steps_per_period
    )
    # Take a break and compute predictions.
    predictions = linear_regressor.predict(input_fn=prediction_input_fn)
    predictions = np.array([item['predictions'][0] for item in predictions])

    # Compute loss.
    root_mean_squared_error = math.sqrt(
        metrics.mean_squared_error(predictions, targets))
    # Occasionally print the current loss.
    print("  period %02d : %0.2f" % (period, root_mean_squared_error))
    # Add the loss metrics from this period to our list.
    root_mean_squared_errors.append(root_mean_squared_error)
    # Finally, track the weights and biases over time.
    # Apply some math to ensure that the data and line are plotted neatly.
    y_extents = np.array([0, sample[my_label].max()])

    weight = linear_regressor.get_variable_value('linear/linear_model/%s/weights' % input_feature)[0]
    bias = linear_regressor.get_variable_value('linear/linear_model/bias_weights')

    x_extents = (y_extents - bias) / weight
    x_extents = np.maximum(np.minimum(x_extents,
                                      sample[my_feature].max()),
                           sample[my_feature].min())
    y_extents = weight * x_extents + bias
    plt.plot(x_extents, y_extents, color=colors[period]) 
  print("Model training finished.")

  # Output a graph of loss metrics over periods.
  plt.subplot(1, 2, 2)
  plt.ylabel('RMSE')
  plt.xlabel('Periods')
  plt.title("Root Mean Squared Error vs. Periods")
  plt.tight_layout()
  plt.plot(root_mean_squared_errors)

  # Output a table with calibration data.
  calibration_data = pd.DataFrame()
  calibration_data["predictions"] = pd.Series(predictions)
  calibration_data["targets"] = pd.Series(targets)
  display.display(calibration_data.describe())

  print("Final RMSE (on training data): %0.2f" % root_mean_squared_error)

调用函数训练 01

train_model(
    learning_rate=0.00001,
    steps=500,
    batch_size=5
)

调用函数训练 02

train_model(
    learning_rate=0.5,
    steps=500,
    batch_size=5
)

可以看到,通过修改学习速率和训练步数以及每批数据数量,可以慢慢的使模型接近于真实值。

8. 切换特征值

我们把特征 total_rooms 切换为 population,来进行预测,可以得到如下的预测结果

train_model(
    learning_rate=0.00002,
    steps=1000,
    batch_size=5,
    input_feature="population"
)

好了,这就是今天的分享了,下次见!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萝卜大杂烩 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 初识 Tensorflow
  • 基础概念
    • 张量:张量是任意维度的数组
      • 指令:指令会创建、销毁和控制张量
        • 图(也称为计算图或数据流图):是一种图数据结构
          • 会话:图必须运行在会话中
            • 实战房价预测
        • 加载必要库
        • 加载数据集
          • 1. 定义特征并配置特征列
          • 2. 定义标签
          • 3. 创建回归模型
          • 4. 定义导入数据函数
          • 5. 训练模型
          • 6. 评估模型
          • 7. 超参数调整
          • 8. 切换特征值
          相关产品与服务
          图数据库 KonisGraph
          图数据库 KonisGraph(TencentDB for KonisGraph)是一种云端图数据库服务,基于腾讯在海量图数据上的实践经验,提供一站式海量图数据存储、管理、实时查询、计算、可视化分析能力;KonisGraph 支持属性图模型和 TinkerPop Gremlin 查询语言,能够帮助用户快速完成对图数据的建模、查询和可视化分析。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档