Tensorflow初接触——房价预测

最近笔者进入学校的机器学习实验室,开始学习相关知识。并跟随极客时间的相关课程学习。

第一次接触机器学习框架Tensorflow,遇到的坑也不少,这里我以吴恩达机器学习的房价数据为基础,用Tensorflow进行简单的线性回归,并使用Tensorboard进行数据流图的可视化

基础概念

首先简要介绍以下Tensorflow的几个概念
1.张量,也就是tensor,我们只需简单的理解为线性代数的向量就行
2.变量,Variable,这是一种特殊的张量,它可以常驻在内存,以进行相应的变化,而其他的张量在干完自己的事情后,就会根据回收机制进行内存的释放
3.占位符,PlaceHolder,这是一个框架,我们需要给他传入向量的行数,列数。它的作用就是预先定义一个没有值的张量框架,等我们需要进行训练的时候,再将数据输入进我们的占位符。当然这里的数据和占位符的维数都要一一对应
4.会话,Session,我们在后面的tensorflow代码中经常会看见
with tf.Session() as sess:
xxx
xxx
xxx
简而言之,会话是一种上下文环境,我们训练模型的时候,需要创建一个单独的会话给它来运行。
5.优化器,Optimizer, 玩过一些机器学习代码的同学应该有用过scipy包里自带的优化器模块,同理于tensorflow的优化器模块,它接受的是一个损失函数,损失函数是机器学习的一个比较重要的概念,这里不展开来讲了,我们可以简单的认为损失函数衡量了你的模型与实际数据的差距,因为我们要尽可能拟合实际数据,所以我们会想要最小化损失函数的值。优化器就可以通过多种算法调整参数,来进行损失函数的最小化,常见的算法有梯度下降算法(一阶导)牛顿迭代法(二阶导)Adam算法。如果我们手动去实现这些算法,需要运用微积分知识,将相关公式对应实现出来。而有了tensorflow框架,我们直接调用就可以了

Tensorflow设计理念

使用Tensorflow实现好一个机器学习的模型后,Tensorflow会以一种图的形式进行连接
在这里插入图片描述
这叫数据流图,我们也可以简单的认为这是一种流程图的形式。经过分块后,每个模块进行执行,对应的输出,再到下一级输入,依次连接起来形成一幅图

上述这个图是我们使用TensorBoard进行可视化得到的
通过整个一幅数据流图,我们可以比较清晰的看到每一步执行的步骤,当机器学习模型的结果出错的时候,我们可以尝试通过数据流图来Debug

实战

数据处理

这里我们通过一个简单的线性方程y = w1x1 + w2x2 + b

import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits import mplot3d
import numpy as np

df1 = pd.read_csv(r'D:\学习资料\机器学习\极客时间Tensorflow\tensorflow-101\notebook-examples\chapter-4\data1.csv', names=['square', 'bedrooms', 'price'])
print(df1.head())

首先我们读入数据并给每一列起名字,分别是square,bedrooms,price
这里价格就是我们要预测的
使用head()方法打印出前五行数据

   square  bedrooms   price
0    2104         3  399900
1    1600         3  329900
2    2400         3  369000
3    1416         2  232000
4    3000         4  539900

可以看出我们这里的几个属性的值,数量级差距较大,我们使用一种标准化的方法,对其进行特征缩放,特征缩放可以缩小各个属性数量级差距,从而在后续的优化算法里面能更快的收敛,更快的最小化代价函数

"""
进行数据规范化
也就是原值减去均值 再除标准差
"""
def normalize_feature(df):
    return df.apply(lambda column: (column - column.mean()) / column.std())

df = normalize_feature(df1)
print(df.head())

由于我们的线性方程中带有一个常数项b,所以我们要给原有的数据集增加一列1,也就是常说的增加偏置

ones = pd.DataFrame({'ones': np.ones(len(df))})
# print(ones)
df = pd.concat([ones, df], axis=1)
# print(df.head())

至此我们的数据处理结束,我们现在开始Tensorflow的模型创建

创建模型

首先定义好我们的学习率和训练轮数
并将对应的数据赋给X_data,y_data

import tensorflow as tf

alpha = 0.01 # 学习率alpha
epoch = 500  # 训练全量数据集的轮数

# 创建线性回归模型(数据流图)
X_data = np.array(df[df.columns[0:3]])
y_data = np.array(df[df.columns[-1]]).reshape(len(df), 1)

接下来我们就要用到之前说的占位符了
我们建立一个张量的框架,对应的维数当然就是X和y的维数了

# 输入X, 形状为47, 3
X = tf.placeholder(tf.float32, X_data.shape)
# 输入y, 形状为47, 1
y = tf.placeholder(tf.float32, y_data.shape)

我们还需要定义一下权重W

# 权重变量W 形状为3, 1
W = tf.get_variable("weights", (X_data.shape[1], 1), initializer=tf.constant_initializer())

这里调用的是get_variable方法,第一个参数是变量的名字,我们把它命名为weights

注意这里的命名大家不要与python中的变量名搞混
W是python中的变量名,也就是我们编程的时候可以去调用的
而weights这个名字是在Tensorflow框架里面所使用的,包括后续的调用(因为在介绍里面有说过变量是一种常驻在内存的张量),数据流图的绘制中,都是以这个名字来进行使用

初始化我们就调用了tf.constant_initializer()这个初始化模块

我们的模型是一个线性模型

假设函数h(x) = w0x0 + w1x1 + w2x2 其中x0 恒为1
所以对应的预测值使用矩阵表就是 X
W

# 推理值
y_pred = tf.matmul(X, W)

接着定义我们的损失函数和优化器,损失函数我们使用的是平方误差函数,也就是常说的最小二乘法,优化器这里使用的是梯度下降优化器

# 损失函数操作 loss
# 两个矩阵都是47 1 ,当transpose_a = True
# 它就把a进行转置,才能应用矩阵的乘法
loss_op = 1 / (2 * len(X_data)) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True)
# 随机梯度下降优化器 opt
opt = tf.train.GradientDescentOptimizer(learning_rate=alpha)
# 单轮训练操作 train_op
train_op = opt.minimize(loss_op)

tf.matmul是矩阵乘法,这里transpose_a = True 是指A矩阵进行转置,A矩阵也就是我们输入的第一个参数,只有转置后我们的矩阵AB才能相乘

接下来我们创建一个会话供模型训练

# 创建会话,训练模型
with tf.Session() as sess:
    # 初始化全局变量
    sess.run(tf.global_variables_initializer())
    # 创建 Filewriter的实例。,以进行TensorBoard的可视化
    writer = tf.summary("D:\pythonProject\Learning_tensorflow\homeprice")

    # 开始训练模型
    # 因为训练集较小,才用梯度下降优化算法,每次都使用全量数据训练
    for e in range(1, epoch+1):
        sess.run(train_op, feed_dict={X:X_data, y:y_data})
        if e % 10 == 0:
            loss, w = sess.run([loss_op, W], feed_dict={X:X_data, y:y_data})
            log_str = "Epoch %d \t loss=%.4g \t Model: y = %.4gxl + %.4gx2 + %.4g"
            print(log_str%(e, loss, w[1], w[2], w[0]))

不知道大家还是否记得之前定义的placeholder,我们只是定义了张量的框架而没有真正把数据喂入,所以这里我们使用的是feed_dict
这个方法是以字典的形式将数据传递给PlaceHolder
之前我们定义的PlaceHolder分别是X和y
而数据是X_data和y_data,所以我们对应的将data传递给占位符

至此我们就可以运行代码进行数据的训练
这里贴上整个代码片

import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits import mplot3d
import numpy as np



df1 = pd.read_csv(r'D:\学习资料\机器学习\极客时间Tensorflow\tensorflow-101\notebook-examples\chapter-4\data1.csv', names=['square', 'bedrooms', 'price'])
print(df1.head())

fig = plt.figure()
# 创建一个Axes3D object
ax = plt.axes(projection='3d')
# 设置三个坐标轴的名称
# ax.set_xlabel('square')
# ax.set_ylabel('bedrooms')
# ax.set_zlabel('price')
# ax.scatter3D(df1['square'], df1['bedrooms'], df1['price'])
# plt.show()

"""
进行数据规范化
也就是原值减去均值 再除标准差
"""
def normalize_feature(df):
    return df.apply(lambda column: (column - column.mean()) / column.std())

df = normalize_feature(df1)
print(df.head())
# 将规范化后的数据再进行一次3d绘图
ax.set_xlabel('square')
ax.set_ylabel('bedrooms')
ax.set_zlabel('price')
ax.scatter3D(df['square'], df['bedrooms'], df['price'])

# plt.show()

"""
插入一列1
用于做第一个偏置
"""
ones = pd.DataFrame({'ones': np.ones(len(df))})
# print(ones)
df = pd.concat([ones, df], axis=1)
# print(df.head())


"""
建立模型
"""
import tensorflow as tf

alpha = 0.01 # 学习率alpha
epoch = 500  # 训练全量数据集的轮数

# 创建线性回归模型(数据流图)

X_data = np.array(df[df.columns[0:3]])
y_data = np.array(df[df.columns[-1]]).reshape(len(df), 1)

# 输入X, 形状为47, 3
X = tf.placeholder(tf.float32, X_data.shape)
# 输入y, 形状为47, 1
y = tf.placeholder(tf.float32, y_data.shape)

# 权重变量W 形状为3, 1

W = tf.get_variable("weights", (X_data.shape[1], 1), initializer=tf.constant_initializer())

# 假设函数h(x) = w0*x0 + w1*x1 + w2*x2 其中x0 恒为1

# 推理值
y_pred = tf.matmul(X, W)

# 损失函数操作 loss
# 两个矩阵都是47 1 ,当transpose_a = True
# 它就把a进行转置,才能应用矩阵的乘法
loss_op = 1 / (2 * len(X_data)) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True)
# 随机梯度下降优化器 opt
opt = tf.train.GradientDescentOptimizer(learning_rate=alpha)
# 单轮训练操作 train_op
train_op = opt.minimize(loss_op)
# 至此我们定义好了数据流图,我们还需要通过一些可视化操作来查看数据流图是否定义正确
# 接下来我们开始训练这张数据流图

# 创建会话,训练模型
with tf.Session() as sess:
    # 初始化全局变量
    sess.run(tf.global_variables_initializer())
    # 开始训练模型
    # 因为训练集较小,才用梯度下降优化算法,每次都使用全量数据训练
    for e in range(1, epoch+1):
        sess.run(train_op, feed_dict={X:X_data, y:y_data})
        if e % 10 == 0:
            loss, w = sess.run([loss_op, W], feed_dict={X:X_data, y:y_data})
            log_str = "Epoch %d \t loss=%.4g \t Model: y = %.4gxl + %.4gx2 + %.4g"
            print(log_str%(e, loss, w[1], w[2], w[0]))

(前面的一小段代码涉及到了数据的简单可视化)

可视化数据流图

我们使用tensorflow自带的工具TensorBoard进行数据流图的可视化
我们需要实现一个Filewriter实例,将数据流图写入对应的路径,然后关闭数据流,再开启TensorBoard进行可视化

但有一个问题是不去分块写入各个步骤,最后使用TensorBoard可视化看起来会很凌乱
所以我们使用name_scope方法进行分块,我们可以简单的理解为就是C语言说的函数作用域,他将各个操作给分块出来,最后再以更加层次的形式展现

这里就直接贴上总代码

import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits import mplot3d
import numpy as np



df1 = pd.read_csv(r'D:\学习资料\机器学习\极客时间Tensorflow\tensorflow-101\notebook-examples\chapter-4\data1.csv', names=['square', 'bedrooms', 'price'])
print(df1.head())

fig = plt.figure()
# 创建一个Axes3D object
ax = plt.axes(projection='3d')
# 设置三个坐标轴的名称
# ax.set_xlabel('square')
# ax.set_ylabel('bedrooms')
# ax.set_zlabel('price')
# ax.scatter3D(df1['square'], df1['bedrooms'], df1['price'])
# plt.show()

"""
进行数据规范化
也就是原值减去均值 再除标准差
"""
def normalize_feature(df):
    return df.apply(lambda column: (column - column.mean()) / column.std())

df = normalize_feature(df1)
print(df.head())
# 将规范化后的数据再进行一次3d绘图
ax.set_xlabel('square')
ax.set_ylabel('bedrooms')
ax.set_zlabel('price')
ax.scatter3D(df['square'], df['bedrooms'], df['price'])

# plt.show()

"""
插入一列1
用于做第一个偏置
"""
ones = pd.DataFrame({'ones': np.ones(len(df))})
# print(ones)
df = pd.concat([ones, df], axis=1)
# print(df.head())


"""
建立模型
"""
import tensorflow as tf

alpha = 0.01 # 学习率alpha
epoch = 500  # 训练全量数据集的轮数

# 创建线性回归模型(数据流图)
X_data = np.array(df[df.columns[0:3]])
y_data = np.array(df[df.columns[-1]]).reshape(len(df), 1)

with tf.name_scope("input"):

    # 输入X, 形状为47, 3
    X = tf.placeholder(tf.float32, X_data.shape, name='X')
    # 输入y, 形状为47, 1
    y = tf.placeholder(tf.float32, y_data.shape, name='y')

with tf.name_scope('hypothesis'):

    # 权重变量W 形状为3, 1

    W = tf.get_variable("weights", (X_data.shape[1], 1), initializer=tf.constant_initializer())

    # 假设函数h(x) = w0*x0 + w1*x1 + w2*x2 其中x0 恒为1

    # 推理值
    y_pred = tf.matmul(X, W, name='y_pred')

with tf.name_scope('loss'):
    # 损失函数操作 loss
    # 两个矩阵都是47 1 ,当transpose_a = True
    # 它就把a进行转置,才能应用矩阵的乘法
    loss_op = 1 / (2 * len(X_data)) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True)

with tf.name_scope('train'):
    # 随机梯度下降优化器 opt
    opt = tf.train.GradientDescentOptimizer(learning_rate=alpha)
    # 单轮训练操作 train_op
    train_op = opt.minimize(loss_op)
    # 至此我们定义好了数据流图,我们还需要通过一些可视化操作来查看数据流图是否定义正确



# 接下来我们开始训练这张数据流图
# 创建会话,训练模型
with tf.Session() as sess:
    # 初始化全局变量
    sess.run(tf.global_variables_initializer())
    # 创建 Filewriter的实例。,以进行TensorBoard的可视化
    writer = tf.summary.FileWriter("D:\pythonProject\Learning_tensorflow\homeprice\logs", sess.graph)

    # 开始训练模型
    # 因为训练集较小,才用梯度下降优化算法,每次都使用全量数据训练
    for e in range(1, epoch+1):
        sess.run(train_op, feed_dict={X:X_data, y:y_data})
        if e % 10 == 0:
            loss, w = sess.run([loss_op, W], feed_dict={X:X_data, y:y_data})
            log_str = "Epoch %d \t loss=%.4g \t Model: y = %.4gxl + %.4gx2 + %.4g"
            print(log_str%(e, loss, w[1], w[2], w[0]))

# 最后关闭输出流
writer.close()

我们在对应的目录下找到了我们的文件
在这里插入图片描述
我们启动tensorBoard但经常会有这么一个报错
在这里插入图片描述
这是因为我们的盘符带有大写字母,而TensorBoard对应代码的格式化只对小写字母格式化,所以我们根据提示,进入到manager.py文件,将里面的%s改为%S

最后我们再启动TensorBoard
我们的格式是这样的
先进入到你文件的上一级目录

tensorboard --logdir 'D:\pythonProject\Learning_tensorflow\homeprice\logs\'

它便会弹出这些提示
在这里插入图片描述
我们就可以登陆到本机的6006端口,推荐使用chrome浏览器,来查看TensorBoard
在这里插入图片描述
整个实战环节就结束了,我也是个刚入门机器学习的小白,希望能把自己的经验分享给大家后,大家能少踩这些坑,热爱上机器学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值