最近笔者进入学校的机器学习实验室,开始学习相关知识。并跟随极客时间的相关课程学习。
第一次接触机器学习框架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
所以对应的预测值使用矩阵表就是 XW
# 推理值
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
整个实战环节就结束了,我也是个刚入门机器学习的小白,希望能把自己的经验分享给大家后,大家能少踩这些坑,热爱上机器学习!