tensorflow入门

1,659 阅读9分钟

PS:对前端和机器学习领域感兴趣的朋友们,可以关注下我的《技术博客》哦!如果对你有帮助,欢迎赠个⭐️,会常更新内容,敬请期待!❤️❤️


以下介绍tensorflow的基础概念和使用(以tensorflow v1.3为例)

语法基础

计算单元与计算过程

计算单元有常量c = tf.constant(2),变量v = tf.Variable(2),占位符p = tf.placeholder(tf.float32)。常见四则运算:

add = tf.add(a, b)
sub = tf.subtract(a, b)
mul = tf.multiply(a, b)
div = tf.divide(a, b)

session 有两种方式:

  1. sess = tf.Session()直接创建sess,但记得要sess.close(),避免内存泄漏
  2. 使用with tf.Session() as sess,利用with关闭会话,意外关闭也会释放资源

注意事项:打印值一定要用sess.run(),否则无法正确打印值

import tensorflow as tf

const1 = tf.constant([[2, 3], [1, 1]])
const2 = tf.constant([[4, 5], [3, 4]])

# matmul 矩阵乘法
mul = tf.matmul(const1, const2)

if const1.graph is tf.compat.v1.get_default_graph():
    print('const1所在的图是当前上下文默认的图')

# 第一种方法 sess.close()关闭会话
sess = tf.Session()
ret = sess.run(mul)
print(ret)
sess.close()

# 第二种方法 利用with关闭会话,意外关闭也会释放资源
# with tf.Session() as sess:
#     ret2 = sess.run(mul)
#     print(ret2)

下面总结下计算过程:

  • 创建数据:可以创建常量、变量和占位符。
  • 构建图:通过前面的数据构建一张图。
  • 初始化:把变量初始化。
  • 计算:必须通过开启一个 Session 来计算图

tensorboard

可视化的数据是数据流图和张量,它们需要在会话中加载或执行操作后才能获取。然后,用户需要使用FileWriter实例将这些数据写入事件文件。最后,启动Tensorboard程序,加载事件文件中的序列化数据,从而可以在各个面板中展示对应的可视化对象。

tensorboard
import tensorflow as tf

w = tf.compat.v1.Variable(2.0, dtype=tf.float32, name="weight")
b = tf.compat.v1.Variable(1.0, dtype=tf.float32, name="bias")
x = tf.placeholder(dtype=tf.float32, name="input")

with tf.name_scope('output'):
    y = w*x+b

path = './log'

# 创建用于初始化变量的操作
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    writer = tf.compat.v1.summary.FileWriter(path, sess.graph)
    result = sess.run(y, {x: 3.0})
    print(result)

执行tensorboard --logdir=log,访问 http://localhost:6006/ 即可。

变量、常量

constant、Variable、placeholder、Parse

hello world程序

import tensorflow as tf

hw = tf.constant('hello world!')

sess = tf.Session()
print(sess.run(hw))

sess.close()

变量示例

import tensorflow as tf

state = tf.Variable(0, name='counter')
one = tf.constant(1)

value = tf.add(state, one)
update = tf.assign(state, value)

init = tf.compat.v1.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(3):
        sess.run(update)
        print(sess.run(state))

placeholder示例

import tensorflow as tf

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)

output = tf.multiply(input1, input2)

with tf.Session() as sess:
    print(sess.run(output, feed_dict={input1: [7.], input2: [2.]}))

实战1:激活函数模拟

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

x = np.linspace(-10, 10, 200)

# 常见激活函数
def sigmoid(inputs):
    y = [1/float(1+np.exp(-x)) for x in inputs]
    return y
def relu(inputs):
    y = [x*(x > 0) for x in inputs]
    return y
def tanh(inputs):
    y = [(np.exp(x)-np.exp(-x))/float(np.exp(x)+np.exp(-x)) for x in inputs]
    return y
def softplus(inputs):
    y = [np.log(1+np.exp(x)) for x in inputs]

# 经过激活函数处理后的y
y_sigmoid = tf.nn.sigmoid(x)
y_relu = tf.nn.relu(x)
y_tanh = tf.nn.tanh(x)
y_softplus = tf.nn.softplus(x)

sess = tf.Session()
y_sigmoid, y_relu, y_tanh, y_softplus = sess.run(
    [y_sigmoid, y_relu, y_tanh, y_softplus])

# 创建图像
plt.subplot(221)
plt.plot(x, y_sigmoid, c='red', label='sigmoid')
plt.ylim(-0.2, 1.2)
plt.legend(loc='best')

plt.subplot(222)
plt.plot(x, y_relu, c='red', label='relu')
plt.ylim(-1, 6)
plt.legend(loc='best')

plt.subplot(223)
plt.plot(x, y_tanh, c='red', label='tanh')
plt.ylim(-1.3, 1.3)
plt.legend(loc='best')

plt.subplot(224)
plt.plot(x, y_softplus, c='red', label='softplus')
plt.ylim(-1, 6)
plt.legend(loc='best')
plt.show()
sess.close()

实战2:梯度下降

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

# 构造数据
num = 100
vectors = []

# 正态随机分布函数生成100个点
for i in range(num):
    x1 = np.random.normal(0, 0.6)
    y1 = 0.1*x1+0.2+np.random.normal(0, 0.04)
    vectors.append([x1, y1])

x_data = [v[0] for v in vectors]
y_data = [v[1] for v in vectors]

# 展示所有随机点
# plt.plot(x_data, y_data, 'r*')
# plt.title = 'linear regression using GD'
# plt.legend()
# plt.show()


# 构建线性回归模型
w = tf.Variable(tf.random_uniform([1], -1, 1))
b = tf.Variable(tf.zeros([1]))
y = w*x_data+b

# 损失函数
loss = tf.reduce_mean(tf.square(y-y_data))
# 梯度下降优化器来优化loss function
optimizer = tf.train.GradientDescentOptimizer(0.5)  # 学习率0.5
train = optimizer.minimize(loss)

# 创建会话,并初始化变量
sess = tf.Session()
init = tf.compat.v1.global_variables_initializer()
sess.run(init)

# 训练20步
for step in range(20):
    sess.run(train)
    # 打印每一步损失,w、b
    print("step:%d,loss:%f,weight:%f,bias:%f" %
          (step, sess.run(loss), sess.run(w), sess.run(b)))


# 绘制最佳拟合曲线
plt.plot(x_data, y_data, 'r*', label='original line')
plt.title = 'linear regression using GD'
plt.plot(x_data, sess.run(w)*x_data+sess.run(b), label='fitted line')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()

sess.close()

实战3:线性回归

import tensorflow as tf
import numpy as np

x_data = np.random.rand(100).astype(np.float32)
y_data = x_data*0.1+0.3

Weigths = tf.Variable(tf.random.uniform([1], -1, 1))
biases = tf.Variable(tf.zeros([1]))

y = Weigths*x_data+biases

loss = tf.reduce_mean(tf.square(y-y_data))
optimizer = tf.compat.v1.train.GradientDescentOptimizer(0.5)  # 学习率
train = optimizer.minimize(loss)

init = tf.compat.v1.global_variables_initializer()

# 创建会话,激活init
sess = tf.compat.v1.Session()
sess.run(init)


for step in range(200):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(Weigths), sess.run(biases))

实战4:聚类

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('mnist_data', one_hot=True)


def add_layer(inputs, in_size, out_size, activation_function=None):
    Weights = tf.Variable(tf.random.normal([in_size, out_size]), name='W')
    baises = tf.Variable(tf.zeros([1, out_size])+0.1, name='b')
    Wx_plus_b = tf.matmul(inputs, Weights)+baises
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs


def compute_accuracy(v_xs, v_ys):
    global prediction
    y_pre = sess.run(prediction, feed_dict={xs: v_xs})
    correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(v_ys, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys})
    return result


# 输入
xs = tf.compat.v1.placeholder(tf.float32, [None, 28*28], name='x_input')
ys = tf.compat.v1.placeholder(tf.float32, [None, 10], name='y_input')
# 输出
prediction = add_layer(xs, 784, 10, activation_function=tf.nn.softmax)
# 交叉熵损失
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys *
                                              tf.log(prediction), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

# 会话
init = tf.compat.v1.global_variables_initializer()
sess = tf.compat.v1.Session()
sess.run(init)

for i in range(1000):
    # 100个100个学习
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={
        xs: batch_xs,
        ys: batch_ys
    })
    if i % 50 == 0:
        print(compute_accuracy(mnist.test.images, mnist.test.labels))

实战5:卷积神经网络CNN

示例1:10个神经元的简单网络

输入1个神经元,隐藏层10个神经元,输出1个神经元,并且动态模拟曲线生成过程

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt


def add_layer(inputs, in_size, out_size, activation_function=None):
    Weights = tf.Variable(tf.random.normal([in_size, out_size]))
    baises = tf.Variable(tf.zeros([1, out_size])+0.1)
    Wx_plus_b = tf.matmul(inputs, Weights)+baises
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs


# 构造数据
x_data = np.linspace(-1, 1, 300)[:, np.newaxis]
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data)-0.5+noise

xs = tf.compat.v1.placeholder(tf.float32, [None, 1])
ys = tf.compat.v1.placeholder(tf.float32, [None, 1])

# 构建神经网络
layer1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
prediction = add_layer(layer1, 10, 1, activation_function=None)

# 损失函数
loss = tf.reduce_mean(tf.reduce_sum(
    tf.square(ys-prediction), reduction_indices=[1]))
train = tf.train.GradientDescentOptimizer(0.1).minimize(loss)


init = tf.compat.v1.global_variables_initializer()
sess = tf.compat.v1.Session()
sess.run(init)

# 原始数据散点分布图
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.scatter(x_data, y_data)
plt.ion()  # 该程序plt.show()后不暂停,继续往下走
plt.show()

for i in range(1000):
    sess.run(train, feed_dict={xs: x_data, ys: y_data})
    if i % 20 == 0:
        # print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))

        # 先抹除这条线
        try:
            ax.lines.remove(lines[0])
        except Exception:
            pass

        prediction_value = sess.run(prediction, feed_dict={
                                    xs: x_data, ys: y_data})
        lines = ax.plot(x_data, prediction_value, 'r-', lw=5)
        plt.pause(0.1)

示例2:加深网络层数

整个流程: 卷积——池化——卷积——池化——全连接——全连接

# 卷积神经网络
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('mnist_data', one_hot=True)

def add_layer(inputs, in_size, out_size, activation_function=None):
    Weights = tf.Variable(tf.random.normal([in_size, out_size]), name='W')
    baises = tf.Variable(tf.zeros([1, out_size])+0.1, name='b')
    Wx_plus_b = tf.matmul(inputs, Weights)+baises
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs


def compute_accuracy(v_xs, v_ys):
    global prediction
    y_pre = sess.run(prediction, feed_dict={xs: v_xs})
    correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(v_ys, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys})
    return result


def weight_variables(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)


def bias_variables(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

# 卷积层
def conv2d(x, W):
    # strides格式 [1,x_movement,y_movement,1]
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

# 池化层
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')


# 输入
xs = tf.compat.v1.placeholder(tf.float32, [None, 28*28], name='x_input')
ys = tf.compat.v1.placeholder(tf.float32, [None, 10], name='y_input')
keep_prob = tf.compat.v1.placeholder(tf.float32)
x_image = tf.reshape(xs, [-1, 28, 28, 1])


# 整个流程:
# 卷积——池化——卷积——池化——全连接——全连接

# conv1 layer
W_conv1 = weight_variables([5, 5, 1, 32])  # 5*5 in_size=1 out_size=32
b_conv1 = bias_variables([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1)+b_conv1)  # output 28*28*32
h_pool1 = max_pool_2x2(h_conv1)  # output 14*14*32

# conv2 layer
W_conv2 = weight_variables([5, 5, 32, 64])  # 5*5 in_size=32 out_size=64
b_conv2 = bias_variables([32])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2)+b_conv2)  # output 14*14*64
h_pool2 = max_pool_2x2(h_conv2)  # output 7*7*64

# func1 layer
W_f1 = weight_variables([7*7*64, 1024])
b_f1 = bias_variables([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_f1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_f1)+b_f1)
h_f1_drop = tf.nn.dropout(h_f1, keep_prob)

# func2 layer
W_f2 = weight_variables([1024, 10])
b_f2 = bias_variables([10])
prediction = tf.nn.softmax(tf.matmul(h_f1_drop, W_f2)+b_f2)


# 输出
prediction = add_layer(xs, 784, 10, activation_function=tf.nn.softmax)
# 交叉熵损失
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys *
                                              tf.log(prediction), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# 会话
init = tf.compat.v1.global_variables_initializer()
sess = tf.compat.v1.Session()
sess.run(init)

for i in range(1000):
    # 100个100个学习
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={
        xs: batch_xs,
        ys: batch_ys
    })
    if i % 50 == 0:
        print(compute_accuracy(mnist.test.images, mnist.test.labels))

示例3: 完整的CNN示例

包括输出层、池化层、卷积层、dropout层、全连接层等 CNN示例3

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

# 载入手写数字库(55000*28*28)
from tensorflow.examples.tutorials.mnist import input_data

# one_hot 独热吗的编码形式
# 0:100000000
# 1:010000000
# 2:001000000
# ……
mnist = input_data.read_data_sets('mnist_data', one_hot=True)


# None表示张量的第一个维度
input_x = tf.placeholder(tf.float32, [None, 28*28])/255
output_y = tf.placeholder(tf.float32, [None, 10])
input_x_images = tf.reshape(input_x, [-1, 28, 28, 1])

# 从测试数据集中选取3000个图片和标签
test_x = mnist.test.images[:3000]
test_y = mnist.test.labels[:3000]

# 构建卷积神经网络

# 第一层卷积,输入28*28*1,卷积5*5*32,输出28*28*32
conv1 = tf.keras.layers.Conv2D(
    inputs=input_x_images,  # 输入
    filters=32,  # 过滤器,输出深度
    kernel_size=5,  # 卷积大小
    strides=1,  # 步长
    padding='same',  # padding,same表示输出大小不变,因此需要补两圈,
    activation=tf.nn.relu
)

# 第一层池化(亚采样),输入28*28*32,输出14*14*32
pool1 = tf.keras.layers.MaxPooling2D(
    inputs=conv1,  # 输入
    pool_size=[2, 2],  # 过滤器大小
    strides=2,  # 步长
)

# 第二层卷积,输入14*14*32,卷积5*5*64,输出14*14*64
conv2 = tf.keras.layers.Conv2D(
    inputs=pool1,  # 输入
    filters=64,  # 过滤器,输出深度
    kernel_size=5,  # 卷积大小
    strides=1,  # 步长
    padding='same',  # padding,same表示输出大小不变,因此需要补两圈,
    activation=tf.nn.relu
)

# 第二层池化,输入14*14*64,输出7*7*64
pool2 = tf.keras.layers.MaxPooling2D(
    inputs=conv2,  # 输入
    pool_size=[2, 2],  # 过滤器大小
    strides=2,  # 步长
)

# 平坦化
flat = tf.reshape(pool2, [-1, 7*7*64])
# 全连接层
dense = tf.keras.layers.Dense(
    inputs=flat,
    units=1024,
    activation=tf.nn.relu
)
# dropouts
dropout = tf.keras.layers.Dropout(inputs=dense, rate=0.5, training=True)
# 10个神经元全连接层,不用激活函数做非线性化,输出1*1*10
logits = tf.keras.layers.Dense(inputs=dropout, units=10)


# 计算误差(计算交叉熵,再用softmax计算概率)
loss = tf.losses.softmax_cross_entropy(onehot_labels=output_y, logits=logits)
# 用Adam优化器最小化误差,学习率0.001
train_op = tf.compat.v1.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
# 精度,计算预测值和实际标签的匹配程度
accuracy = tf.compat.v1.metrics.accuracy(
    labels=tf.argmax(output_y, axis=1),
    predictions=tf.argmax(logits, axis=1)[1]
)


# 创建会话
sess = tf.compat.v1.Session()
# 初始化变量:全局和局部
init = tf.group(tf.compat.v1.global_variables_initializer,
                tf.compat.v1.local_variables_initializer)
sess.run(init)

for i in range(20000):
  # 从train训练集中取下一50个样本
    batch = mnist.train.next_batch(50)
    train_loss, train_op = sess.run([loss, train_op], {
        input_x: batch[0],
        output_y: batch[1]}
    )
    if i % 100 == 0:
        test_accuracy = sess.run(accuracy, {
            input_x: test_x,
            output_y: test_y
        })
        print('step:%d,loss=%.4f,test_accuracy:%.2f' %
              (i, train_loss, test_accuracy))


# 测试:打印20个预测值和真实值比对
test_output = sess.run(logits, {input_x: test_x[:20]})
predict_y = np.argmax(test_output, 1)
print(predict_y, 'predict_y')
print(np.argmax(test_y[:20], 1), 'real number')

实战6:模型保存与读取

tensorflow目前只能保存Variable,不能保存整个神经框架,需要重新定义一下框架,再把Variable放进来重新学习

CNN示例3

存入文件:

import tensorflow as tf
import numpy as np

# save to file
# remember to define the same dtype and shape where restore
W = tf.Variable([[1, 2, 3], [4, 5, 6]], dtype=tf.float32)
b = tf.Variable([[1, 2, 3]], dtype=tf.float32)

init = tf.compat.v1.global_variables_initializer()

saver = tf.compat.v1.train.Saver()

with tf.compat.v1.Session() as sess:
    sess.run(init)
    # 这里tensorflow推荐使用ckpt后缀名
    saver_path = saver.save(sess, 'net/save_net.ckpt')

读取文件:

import tensorflow as tf
import numpy as np

# restore variables
# redefine same dtype and shape for your variables
# define empty framework

W = tf.Variable(np.arange(6).reshape((2, 3)), dtype=tf.float32)
b = tf.Variable(np.arange(3).reshape((1, 3)), dtype=tf.float32)

# not need init step

saver = tf.compat.v1.train.Saver()
with tf.compat.v1.Session() as sess:
    saver.restore(sess, 'net/save_net.ckpt')
    print('weight:', sess.run(W))
    print('bias:', sess.run(b))

安装与转化

搭建虚拟环境安装

  1. 安装conda 可以使用清华镜像源,安装Miniconda 即可(注意配置环境变量)

  2. 在终端检查conda命令是否可用,并创建指定python版本的虚拟环境

conda create -n [name] python=3.6.8 创建虚拟环境
conda remove -n [name] --all 删除虚拟环境
conda info --envs 查看虚拟环境
conda activate [name] 激活虚拟环境(可以发现python版本已经改变)
conda deactivate [name] 退出虚拟环境
  1. 安装tfjs converter pip install tensorflowjs安装 tensorflowjs_converter -h检查是否安装成功

直接pip安装

Tensorflow2.0可以直接用pip安装:pip install tensorflow==2.0.0-alpha0 如果速度比较慢,可以换国内清华源, 在终端执行下面命令:

# 升级 pip 到最新的版本 (>=10.0.0) 后进行配置:
pip install pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

然后重新运行安装命令:pip install tensorflow==2.0.0-alpha0 ,这样,就可以开始使用tensorflow 2.0了

python与js模型的互转

  1. 准备工作 conda activate [name]激活 tensorflowjs_converter检查

  2. 开始转换——具体格式建议看文档(github tfjs-converter)

  • 1)python模型转js模型 tensorflowjs_converter --input_format=keras --output_format=tf_layers_model [input_path] [output_path]
  • 2)js模型转python模型 tensorflowjs_converter --input_format=tf_layers_model --output_format=keras [input_path] [output_path]
  1. 验证模型正确性

模型加速

  1. 分片(--weight_shared_size_bytes=[size]) tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_layers_model --weight_shared_size_bytes=100000 [input_path] [output_path] 在输出文件夹中会发现很多块分片后的模型,这样在加载模型时可以使用并发实现加速

  2. 量化(--quantization_bytes=[n]) tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_layers_model --quantization_bytes=2 [input_path] [output_path]

  3. 通过转为tfjs_graph_model来加速模型——内部实现了凸优化(--output_format=tf_graph_model) tensorflowjs_converter --input_format=tf_layers_model --output_format=tf_graph_model [input_path] [output_path]