前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >TensorBoard计算加速

TensorBoard计算加速

作者头像
py3study
发布于 2020-01-15 14:57:03
发布于 2020-01-15 14:57:03
75900
代码可运行
举报
文章被收录于专栏:python3python3
运行总次数:0
代码可运行

TensorBoard计算加速

0. 写在前面

参考书

《TensorFlow:实战Google深度学习框架》(第2版)

工具

python3.5.1,pycharm

1. TensorFlow使用GPU

1. 如何使用log_device_placement参数来打印运行每一个运算的设备。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test1.py
@time: 2019/5/14 19:40
@desc: 如何使用log_device_placement参数来打印运行每一个运算的设备
"""

import tensorflow as tf

a = tf.constant([1.0, 2.0, 3.0], shape=[3], name='a')
b = tf.constant([1.0, 2.0, 3.0], shape=[3], name='b')
c = a + b
# 通过log_device_placement参数来输出运行每一个运算的设备。
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
print(sess.run(c))

运行结果:

2. 通过tf.device手工指定运行设备的样例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test2.py
@time: 2019/5/14 19:54
@desc: 通过tf.device手工指定运行设备的样例。
"""

import tensorflow as tf

# 通过tf.device将运行指定到特定的设备上。
with tf.device('/cpu:0'):
    a = tf.constant([1.0, 2.0, 3.0], shape=[3], name='a')
    b = tf.constant([1.0, 2.0, 3.0], shape=[3], name='b')

with tf.device('/gpu:1'):
    c = a + b

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
print(sess.run(c))

由于我并没有GPU,所以只是尬码代码。。。

3. 不是所有的操作都可以被放在GPU上,如果强行将无法放在GPU上的操作指定到GPU上,那么程序将会报错。

4. 为了避免这个问题,TensorFlow在生成会话时,可以指定allow_soft_placement参数,当这个参数为True时,如果运算无法由GPU执行,那么TensorFlow会自动将它放到CPU上执行。

2. 深度学习训练并行模式

  1. 常用的并行化深度学习模型训练方式有两种,同步模式异步模式
  2. 可以简单的认为异步模式就是单机模式复制了多份,每一份使用不同的训练数据进行训练。
  3. 异步模式下,不同设备之间是完全独立的。
  4. 使用异步模式训练的深度学习模型有可能无法达到较优的训练结果。
  5. 同步模式下,所有的设备同时读取参数的取值,并且当反向传播算法完成之后同步更新参数的取值。
  6. 总结来说就是,异步模式达到全局最优要难一些,但是速度快;同步模式更能达到全局最优,但墨迹。两者都有应用。

3. 多GPU并行

在多GPU上训练深度学习模型解决MNIST问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test3.py
@time: 2019/5/15 10:35
@desc: 在多GPU上训练深度学习模型解决MNIST问题。
"""

from datetime import datetime
import os
import time

import tensorflow as tf
import BookStudy.book2.mnist_inference as mnist_inference


# 定义训练神经网络时需要用到的模型。
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.001
LEARNING_RATE_DECAY = 0.99
REGULARAZTION_RATE = 0.0001
TRAINING_STEPS = 1000
MOVING_AVERAGE_DECAY = 0.99
N_GPU = 2

# 定义日志和模型输出的路径
MODEL_SAVE_PATH = 'logs_and_models/'
MODEL_NAME = 'model.ckpt'

# 定义数据存储的路径。因为需要为不同的GPU提供不同的训练数据,所以通过placeholder的方式
# 就需要手动准备多份数据。为了方便训练数据的获取过程,可以采用前面介绍的Dataset的方式从
# TFRecord中读取数据。于是在这里提供的数据文件路径为将MNIST训练数据转化为TFRecord格式
# 之后的路径。如何将MNIST数据转化为TFRecord格式在前面有详细介绍,这里不再赘述。
DATA_PATH = 'output.tfrecords'


# 定义输入队列得到的训练数据,具体细节可以参考前面。
def get_input():
    dataset = tf.data.TFRecordDataset([DATA_PATH])

    # 定义数据解析格式。
    def parser(record):
        features = tf.parse_single_example(
            record,
            features={
                'image_raw': tf.FixedLenFeature([], tf.string),
                'pixels': tf.FixedLenFeature([], tf.int64),
                'label': tf.FixedLenFeature([], tf.int64),
            }
        )

        # 解析图片和标签信息。
        decoded_image = tf.decode_raw(features['image_raw'], tf.uint8)
        reshaped_image = tf.reshape(decoded_image, [784])
        retyped_image = tf.cast(reshaped_image, tf.float32)
        label = tf.cast(features['label', tf.int32])

        return retyped_image, label

    # 定义输入队列
    dataset = dataset.map(parser)
    dataset = dataset.shuffle(buffer_size=10000)
    dataset = dataset.repeat(10)
    dataset = dataset.batch(BATCH_SIZE)
    iterator = dataset.make_one_shot_iterator()

    features, labels = iterator.get_next()
    return features, labels


# 定义损失函数。对于给定的训练数据、正则化损失计算规则和命名空间,计算在这个命名空间下的总损失。
# 之所以需要给定命名空间就是因为不同的GPU上计算得出的正则化损失都会加入名为loss的集合,如果不
# 通过命名空间就会将不同GPU上的正则化损失都加进来。
def get_loss(x, y_, regularizer, scope, reuse_variables=None):
    # 沿用前面定义的函数来计算神经网络的前向传播结果。
    with tf.variable_scope(tf.get_variable_scope(), reuse=reuse_variables):
        y = mnist_inference.inference(x, regularizer)
    # 计算交叉熵损失。
    cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=y_))
    # 计算当前GPU上计算得到的正则化损失。
    regularization_loss = tf.add_n(tf.get_collection('losses', scope))
    # 计算最终的总损失。
    loss = cross_entropy + regularization_loss
    return loss


# 计算每一个变量梯度的平均值。
def average_gradients(tower_grads):
    average_grads = []

    # 枚举所有的变量和变量在不同GPU上计算得出的梯度。
    for grad_and_vars in zip(*tower_grads):
        # 计算所有GPU上的梯度平均值
        grads = []
        for g, _ in grad_and_vars:
            expanded_g = tf.expand_dims(g, 0)
            grads.append(expanded_g)
        grad = tf.concat(grads, 0)
        grad = tf.reduce_mean(grad, 0)

        v = grad_and_vars[0][1]
        grad_and_var = (grad, v)
        # 将变量和它的平均梯度对应起来。
        average_grads.append(grad_and_var)

    # 返回所有变量的平均梯度,这个将被用于变量的更新。
    return average_grads


# 主训练过程。
def main(argv=None):
    # 将简单的运算放在CPU上,只有神经网络的训练过程在GPU上。
    with tf.Graph().as_default(), tf.device('/cpu:0'):
        # 定义基本的训练过程
        x, y_ = get_input()
        regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)

        global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0), trainable=False)
        learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, 60000/BATCH_SIZE, LEARNING_RATE_DECAY)

        opt = tf.train.GradientDescentOptimizer(learning_rate)

        tower_grads = []
        reuse_variables = False
        # 将神经网络的优化过程跑在不同的GPU上。
        for i in range(N_GPU):
            # 将优化过程指定在一个GPUwith tf.device('/gpu:%d' % i):
                with tf.name_scope('GPU_%d' % i) as scope:
                    cur_loss = get_loss(x, y_, regularizer, scope, reuse_variables)
                    # 在第一次声明变量之后,将控制变量重用的参数设置为True。这样可以让不同的GPU更新同一组参数
                    reuse_variables = True
                    grads = opt.compute_gradients(cur_loss)
                    tower_grads.append(grads)

    # 计算变量的平均梯度
    grads = average_gradients(tower_grads)
    for grad, var in grads:
        if grad is not None:
            tf.summary.histogram('gradients_on_average/%s' % var.op.name, grad)

    # 使用平均梯度更新参数。
    apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
    for var in tf.trainable_variables():
        tf.summary.histogram(var.op.name, var)

    # 计算变量的滑动平均值。
    variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
    variable_to_average = (tf.trainable_variables() + tf.moving_average_variables())
    variable_averages_op = variable_averages.apply(variable_to_average)
    # 每一轮迭代需要更新变量的取值并更新变量的滑动平均值
    train_op = tf.group(apply_gradient_op, variable_averages_op)

    saver = tf.train.Saver()
    summary_op = tf.summary.merge_all()
    init = tf.global_variables_initializer()
    with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)) as sess:
        # 初始化所有变量并启动队列。
        init.run()
        summary_writer = tf.summary.FileWriter(MODEL_SAVE_PATH, sess.graph)

        for step in range(TRAINING_STEPS):
            # 执行神经网络训练操作,并记录训练操作的运行时间。
            start_time = time.time()
            _, loss_value = sess.run([train_op, cur_loss])
            duration = time.time() - start_time

            # 每隔一段时间输出当前的训练进度,并统计训练速度
            if step != 0 and step % 10 == 0:
                # 计算使用过的训练数据个数。因为在每一次运行训练操作时,每一个GPU都会使用一个batch的训练数据,
                # 所以总共用到的训练数据个数为batch大小 X GPU个数。
                num_examples_per_step = BATCH_SIZE * N_GPU

                # num_example_per_step为本次迭代使用到的训练数据个数,duration为运行当前训练过程使用的时间,
                # 于是平均每秒可以处理的训练数据个数为num_examples_per_step / duration
                examples_per_sec = num_examples_per_step / duration

                # duration为运行当前训练过程使用的时间,因为在每一个训练过程中,每一个GPU都会使用一个batch的
                # 训练数据,所以在单个batch上的训练所需要的时间为duration / GPU个数
                sec_per_batch = duration / N_GPU

                # 输出训练信息。
                format_str = '%s: step %d, loss = %.2f (%.1f examples/sec; %.3f sec/batch)'
                print(format_str % (datetime.now(), step, loss_value, examples_per_sec, sec_per_batch))

                # 通过TensorBoard可视化训练过程。
                summary = sess.run(summary_op)
                summary_writer.add_summary(summary, step)

            # 每隔一段时间保存当前的模型。
            if step % 1000 == 0 or (step + 1) == TRAINING_STEPS:
                checkpoint_path = os.path.join(MODEL_SAVE_PATH, MODEL_NAME)
                saver.save(sess, checkpoint_path, global_step=step)


if __name__ == '__main__':
    tf.app.run()

由于我依然没有GPU,所以只是尬码代码。。。

4. 分布式TensorFlow

4.1 分布式TensorFlow原理

  1. 创建一个最简单的TensorFlow集群。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test4.py
@time: 2019/5/15 22:19
@desc: 创建一个最简单的TensorFlow集群
"""

import tensorflow as tf
c = tf.constant("Hello, distributed TensorFlow!")
# 创建一个本地的TensorFlow集群
server = tf.train.Server.create_local_server()
# 在集群上创建一个会话。
sess = tf.Session(server.target)
# 输出Hello,distributed TensorFlow!
print(sess.run(c))

输出得到:

  1. 在本地运行有两个任务的TensorFlow集群。

第一个任务代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test5.py
@time: 2019/5/15 22:27
@desc: 在本地运行有两个任务的TensorFlow集群。第一个任务的代码。
"""

import tensorflow as tf
c = tf.constant("Hello from server1!")

# 生成一个有两个任务的集群,一个任务跑在本地2222端口,另外一个跑在本地2223端口。
cluster = tf.train.ClusterSpec({"local": ["localhost: 2222", "localhost: 2223"]})
# 通过上面生成的集群配置生成Server,并通过job_name和task_index指定当前所启动的任务。
# 因为该任务是第一个任务,所以task_index为0.
server = tf.train.Server(cluster, job_name="local", task_index=0)

# 通过server.target生成会话来使用TensorFlow集群中的资源。通过设置
# log_device_placement可以看到执行每一个操作的任务。
sess = tf.Session(server.target, config=tf.ConfigProto(log_device_placement=True))
print(sess.run(c))
server.join()

第二个任务代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test6.py
@time: 2019/5/16 10:14
@desc: 在本地运行有两个任务的TensorFlow集群。第二个任务的代码。
"""

import tensorflow as tf
c = tf.constant("Hello from server2!")

# 和第一个程序一样的集群配置。集群中的每一个任务需要采用相同的配置。
cluster = tf.train.ClusterSpec({"local": ["localhost: 2222", "localhost: 2223"]})
# 指定task_index为1,所以这个程序将在localhost: 2223启动服务。
server = tf.train.Server(cluster, job_name="local", task_index=1)

# 剩下的代码都和第一个任务的代码一致。
# 通过server.target生成会话来使用TensorFlow集群中的资源。通过设置
# log_device_placement可以看到执行每一个操作的任务。
sess = tf.Session(server.target, config=tf.ConfigProto(log_device_placement=True))
print(sess.run(c))
server.join()

启动第一个任务后,可以得到类似下面的输出:

从第一个任务的输出中可以看到,当只启动第一个任务时,程序会停下来等待第二个任务启动。当第二个任务启动后,可以得到如下输出:

值得注意的是:第二个任务中定义的计算也被放在了同一个设备上,也就是说这个计算将由第一个任务来执行。

使用分布式TensorFlow训练深度学习模型一般有两种方式:

  1. 一种方式叫做计算图内分布式(in-graph replication)。优点:同步更新参数比较容易控制。缺点:当数据量太大时,中心节点容易造成性能瓶颈。
  2. 另外一种叫做计算图之间分布式(between-graph replication)。优点:并行程度更高。缺点:同步更新困难。

4.2 分布式TensorFlow模型训练

异步模式样例程序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test7.py
@time: 2019/5/16 14:01
@desc: 实现异步模式的分布式神经网络训练过程。
"""

import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_inference


# 配置神经网络的参数。
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.001
LEARNING_RATE_DECAY = 0.99
REGULARAZTION_RATE = 0.0001
TRAINING_STEPS = 20000
MOVING_AVERAGE_DECAY = 0.99

# 模型保存的路径。
MODEL_SAVE_PATH = "./log1"
# MNIST数据路径。
DATA_PATH = "D:/Python3Space/BookStudy/book2/MNIST_data"

# 通过flags指定运行的参数。在前面对于不同的任务(task)给出了不同的程序。
# 但这不是一种可扩展的方式。在这一节中将使用运行程序时给出的参数来配置在
# 不同任务中运行的程序。
FLAGS = tf.app.flags.FLAGS

# 指定当前运行的是参数服务器还是计算服务器。参数服务器只负责TensorFlow中变量的维护
# 和管理,计算服务器负责每一轮迭代时运行反向传播过程。
tf.app.flags.DEFINE_string('job_name', 'worker', ' "ps" or "worker" ')
# 指定集群中的参数服务器地址。
tf.app.flags.DEFINE_string(
    'ps_hosts', ' tf-ps0:2222,tf-ps1:1111',
    'Comma-separated list of hostname:port for the parameter server jobs.'
    ' e.g. "tf-ps0:2222,tf-ps1:1111" '
)

# 指定集群中的计算服务器地址。
tf.app.flags.DEFINE_string(
    'worker_hosts', ' tf-worker0:2222, tf-worker1:1111',
    'Comma-separated list of hostname:port for the worker jobs. '
    'e.g. "tf-worker0:2222,tf-worker1:1111" '
)

# 指定当前程序的任务ID。TensorFlow会自动根据参数服务器/计算服务器列表中的端口号来启动服务。
# 注意参数服务器和计算服务器的编号都是从0开始的。
tf.app.flags.DEFINE_integer(
    'task_id', 0, 'Task ID of the worker/replica running the training.'
)


# 定义TensorFlow的计算图,并返回每一轮迭代时需要运行的操作。这个过程和前面的主函数基本一致,
# 但为了使处理分布式计算的部分更加突出,这里将此过程整理为一个函数。
def build_model(x, y_, is_chief):
    regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)
    # 通过前面给出的mnist_inference计算神经网络前向传播的结果。
    y = mnist_inference.inference(x, regularizer)
    global_step = tf.train.get_or_create_global_step()

    # 计算损失函数并定义反向传播的过程。
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
    cross_entropy_mean = tf.reduce_mean(cross_entropy)
    loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))
    learning_rate = tf.train.exponential_decay(
        LEARNING_RATE_BASE,
        global_step,
        60000 / BATCH_SIZE,
        LEARNING_RATE_DECAY
    )

    train_op = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)

    # 定义每一轮迭代需要运行的操作。
    if is_chief:
        # 计算变量的滑动平均值。
        variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
        variable_averages_op = variable_averages.apply(tf.trainable_variables())
        with tf.control_dependencies([variable_averages_op, train_op]):
            train_op = tf.no_op()
    return global_step, loss, train_op


def main(argv=None):
    # 解析flags并通过tf.train.ClusterSpe配置TensorFlow集群。
    ps_hosts = FLAGS.ps_hosts.split(',')
    worker_hosts = FLAGS.worker_hosts.split(',')
    cluster = tf.train.ClusterSpec({'ps': ps_hosts, 'worker': worker_hosts})
    # 通过tf.train.ClusterSpec以及当前任务创建tf.train.Server。
    server = tf.train.Server(cluster, job_name=FLAGS.job_name, task_index=FLAGS.task_id)

    # 参数服务器只需要管理TensorFlow中的变量,不需要执行训练的过程。server.join()会一直停在这条语句上。
    if FLAGS.job_name == 'ps':
        with tf.device("/cpu:0"):
            server.join()

    # 定义计算服务器需要运行的操作。
    is_chief = (FLAGS.task_id == 0)
    mnist = input_data.read_data_sets(DATA_PATH, one_hot=True)

    # 通过tf.train.replica_device_setter函数来指定执行每一个运算的设备。
    # tf.train.replica_device_setter函数会自动将所有的参数分配到参数服务器上,将
    # 计算分配到当前的计算服务器上。
    device_setter = tf.train.replica_device_setter(
        worker_device="/job:worker/task:%d" % FLAGS.task_id,
        cluster=cluster
    )

    with tf.device(device_setter):
        # 定义输入并得到每一轮迭代需要运行的操作。
        x = tf.placeholder(
            tf.float32,
            [None, mnist_inference.INPUT_NODE],
            name='x-input'
        )
        y_ = tf.placeholder(
            tf.float32,
            [None, mnist_inference.OUTPUT_NODE],
            name='y-input'
        )
        global_step, loss, train_op = build_model(x, y_, is_chief)

        hooks = [tf.train.StopAtStepHook(last_step=TRAINING_STEPS)]
        sess_config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)

        # 通过tf.train.MonitoredTrainingSession管理训练深度学习模型的通用功能。
        with tf.train.MonitoredTrainingSession(
            master=server.target,
            is_chief=is_chief,
            checkpoint_dir=MODEL_SAVE_PATH,
            hooks=hooks,
            save_checkpoint_secs=60,
            config=sess_config
        ) as mon_sess:
            print("session started.")
            step = 0
            start_time = time.time()

            # 执行迭代过程。在迭代过程中tf.train.MonitoredTrainingSession会帮助完成初始化、
            # 从checkpoint中加载训练过的模型、输出日志并保存模型,所以以下程序中不需要再调用
            # 这些过程。tf.train.StopAtStepHook会帮忙判断是否需要退出。
            while not mon_sess.should_stop():
                xs, ys = mnist.train.next_batch(BATCH_SIZE)
                _, loss_value, global_step_value = mon_sess.run(
                    [train_op, loss, global_step],
                    feed_dict={x: xs, y_: ys}
                )

                # 每隔一段时间输出训练信息,不同的计算服务器都会更新全局的训练轮数,
                # 所以这里使用global_step_value得到在训练中使用过的batch的总数。
                if step > 0 and step % 100 == 0:
                    duration = time.time() - start_time
                    sec_per_batch = duration / global_step_value
                    format_str = "After %d training steps (%d global steps), loss on training batch is %g. (%.3f sec/batch)"
                    print(format_str % (step, global_step_value, loss_value, sec_per_batch))

                step += 1


if __name__ == '__main__':
    try:
        tf.app.run()
    except Exception as e:
        print(e)

要启动一个拥有一个参数服务器、两个计算服务器的集群,需要现在运行参数服务器的机器上启动以下命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python gpu_test7.py --job_name=ps --task_id=0 --ps_hosts=localhost:2222 --worker_hosts=localhost:2223,localhost:2224

然后再运行第一个计算服务器的机器上启动以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python gpu_test7.py --job_name=worker --task_id=0 --ps_hosts=localhost:2222 --worker_hosts=localhost:2223,localhost:2224

最后再运行第二个计算服务器的机器上启动以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python gpu_test7.py --job_name=worker --task_id=1 --ps_hosts=localhost:2222 --worker_hosts=localhost:2223,localhost:2224

注意:如果你报错了:

1. UnknownError: Could not start gRPC server

一定是你的参数问题!检查你的task_id有没有写成taske_id等等,类似的,一定是这样!!!一定要跟程序中的参数名保持一致!!!

2. 跑的过程中python搞不清楚崩了,两个计算服务器都会崩,跟时间无关,随机的那种。。。直接弹出python已停止的那种

听我的换台电脑或者重装系统。

3. 报错‘ps’不存在的,没定义的注意了!

在cmd(windows系统)中启动上面三个命令的时候,参数的内容不要加引号!!!书上面加引号真的是坑死了好吗!

我就是解决了上述三个问题,换了台macbook,才总算功德圆满了跑出了结果。

左上:参数服务器

右上:计算服务器0

左下:计算服务器1

右下:运行tensorboard,结果如下:

同步模式样例程序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8 

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: gpu_test8.py
@time: 2019/5/17 13:52
@desc: 实现同步模式的分布式神经网络训练过程。
"""

import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_inference

# 配置神经网络的参数。
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.001
LEARNING_RATE_DECAY = 0.99
REGULARAZTION_RATE = 0.0001
TRAINING_STEPS = 20000
MOVING_AVERAGE_DECAY = 0.99

# 模型保存的路径。
MODEL_SAVE_PATH = "./log2"
# MNIST数据路径。
DATA_PATH = "D:/Python3Space/BookStudy/book2/MNIST_data"

# 和异步模式类似的设置flags。
FLAGS = tf.app.flags.FLAGS

tf.app.flags.DEFINE_string('job_name', 'worker', ' "ps" or "worker" ')
tf.app.flags.DEFINE_string(
    'ps_hosts', ' tf-ps0:2222, tf-ps1:1111',
    'Comma-separated list of hostname:port for the parameter server jobs.'
    ' e.g. "tf-ps0:2222,tf-ps1:1111" '
)
tf.app.flags.DEFINE_string(
    'worker_hosts', ' tf-worker0:2222, tf-worker1:1111',
    'Comma-separated list of hostname:port for the worker jobs. '
    'e.g. "tf-worker0:2222,tf-worker1:1111" '
)
tf.app.flags.DEFINE_integer(
    'task_id', 0, 'Task ID of the worker/replica running the training.'
)


# 和异步模式类似的定义TensorFlow的计算图。唯一的区别在于使用。
# tf.train.SyncReplicasOptimizer函数处理同步更新。
def build_model(x, y_, n_workers,  is_chief):
    regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)
    y = mnist_inference.inference(x, regularizer)
    global_step = tf.train.get_or_create_global_step()

    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
    cross_entropy_mean = tf.reduce_mean(cross_entropy)
    loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))
    learning_rate = tf.train.exponential_decay(
        LEARNING_RATE_BASE,
        global_step,
        60000 / BATCH_SIZE,
        LEARNING_RATE_DECAY
    )

    # 通过tf.train.SyncReplicasOptimizer函数实现同步更新。
    opt = tf.train.SyncReplicasOptimizer(
        tf.train.GradientDescentOptimizer(learning_rate),
        replicas_to_aggregate=n_workers,
        total_num_replicas=n_workers
    )
    sync_replicas_hook = opt.make_session_run_hook(is_chief)
    train_op = opt.minimize(loss, global_step=global_step)

    if is_chief:
        variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
        variable_averages_op = variable_averages.apply(tf.trainable_variables())
        with tf.control_dependencies([variable_averages_op, train_op]):
            train_op = tf.no_op()
    return global_step, loss, train_op, sync_replicas_hook


def main(argv=None):
    # 和异步模式类似地创建TensorFlow集群。
    ps_hosts = FLAGS.ps_hosts.split(',')
    worker_hosts = FLAGS.worker_hosts.split(',')
    n_workers = len(worker_hosts)
    cluster = tf.train.ClusterSpec({"ps": ps_hosts, "worker": worker_hosts})

    server = tf.train.Server(cluster,
                             job_name=FLAGS.job_name,
                             task_index=FLAGS.task_id)

    if FLAGS.job_name == 'ps':
        with tf.device("/cpu:0"):
            server.join()

    is_chief = (FLAGS.task_id == 0)
    mnist = input_data.read_data_sets(DATA_PATH, one_hot=True)

    device_setter = tf.train.replica_device_setter(
        worker_device="/job:worker/task:%d" % FLAGS.task_id,
        cluster=cluster
    )

    with tf.device(device_setter):
        # 定义输入并得到每一轮迭代需要运行的操作。
        x = tf.placeholder(
            tf.float32,
            [None, mnist_inference.INPUT_NODE],
            name='x-input'
        )
        y_ = tf.placeholder(
            tf.float32,
            [None, mnist_inference.OUTPUT_NODE],
            name='y-input'
        )
        global_step, loss, train_op, sync_replicas_hook = build_model(x, y_, n_workers, is_chief)

        # 把处理同步更新的hook也加进来
        hooks = [sync_replicas_hook, tf.train.StopAtStepHook(last_step=TRAINING_STEPS)]
        sess_config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)

        # 训练过程和异步一致。
        with tf.train.MonitoredTrainingSession(
            master=server.target,
            is_chief=is_chief,
            checkpoint_dir=MODEL_SAVE_PATH,
            hooks=hooks,
            save_checkpoint_secs=60,
            config=sess_config
        ) as mon_sess:
            print("session started.")
            step = 0
            start_time = time.time()

            while not mon_sess.should_stop():
                xs, ys = mnist.train.next_batch(BATCH_SIZE)
                _, loss_value, global_step_value = mon_sess.run(
                    [train_op, loss, global_step],
                    feed_dict={x: xs, y_: ys}
                )

                if step > 0 and step % 100 == 0:
                    duration = time.time() - start_time
                    sec_per_batch = duration / global_step_value
                    format_str = "After %d training steps (%d global steps), loss on training batch is %g. (%.3f sec/batch)"
                    print(format_str % (step, global_step_value, loss_value, sec_per_batch))

                step += 1


if __name__ == '__main__':
    tf.app.run()

同上运行出来得到:

和异步模式不同,在同步模式下,global_step差不多是两个计算服务器local_step的平均值。比如在第二个计算服务器还没有开始之前,global_step是第一个服务器local_step的一般。这是因为同步模式要求收集replicas_to_average份梯度才会开始更新(注意这里TensorFlow不要求每一份梯度来自不同的计算服务器)。同步模式不仅仅是一次使用多份梯度,tf.train.SyncReplicasOptimizer的实现同时也保证了不会出现陈旧变量的问题,该函数会记录每一份梯度是不是由最新的变量值计算得到的,如果不是,那么这一份梯度将会被丢弃。

5. 写在最后

总算是把这本书一步一步的实现,一步一步的修改,从头认认真真的刷了一遍。取其精华,弃其糟粕。学习TensorFlow真的是一件不容易,也是一件很有成就感的过程。还有黑皮书《TensorFlow实战》和圣经花书《深度学习》要学,希望后面的书不会让我失望吧。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/06/06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
DJI TT无人机 microPython编程指南
我这里还是希望dji可以把这个mpy的一些源码放出来,因为我觉得是无关紧要的东西,然后去学习一下。而不是这样盲目的去猜。
云深无际
2022/02/09
1.7K0
DJI TT无人机 microPython编程指南
eps32和ros2之稳稳点亮一个LED灯(IO4)
esp32与ros2的开关灯 源码: #include <ros2arduino.h> #include <WiFi.h> #include <WiFiUdp.h> #include <WiFiClient.h> //#include <WebServer.h> //#include <ESPmDNS.h> #define SSID "***" #define SSID_PW "***" #define AGENT_IP "***" #define AGENT_PORT *** /
zhangrelay
2021/12/02
5340
eps32和ros2之稳稳点亮一个LED灯(IO4)
涵盖 Java 核心知识的综合指南:JavaGuide | 开源日报 0912
这是一份涵盖大部分 Java 程序员所需要掌握的核心知识库。该项目包含了 Java 基础、集合、IO、并发等方面的内容,并提供了重要知识点详解和源码分析。此外还有计算机基础(操作系统、网络)、数据库(MySQL、Redis)以及常用框架(Spring/SpringBoot)等相关内容。对于想要准备 Java 面试或者加强自己技术能力的程序员来说,JavaGuide 是一个不错的选择。
小柒
2023/09/14
3170
涵盖 Java 核心知识的综合指南:JavaGuide | 开源日报 0912
用安信可Ai-WB2-01S做一个可用网页控制的简易灯
●管理界面:浏览器地址栏"设备ip/LAMP/",比如"http://192.168.0.127/LAMP"
安信可科技
2025/03/26
590
利用esp8266做一个物联网小灯
按照知识共享署名-非商业性使用 4.0 国际协议进行许可,转载引用文章应遵循相同协议。
逍遥子大表哥
2021/12/17
1K0
利用esp8266做一个物联网小灯
Arduino配置WS2812及Adafruit_NeoPixel库的使用
    其主要应用领域有LED全彩发光字灯串,全彩LED模组,LED像素屏,各种电子产品,电子设备跑马灯等。     WS2812最牛的地方除了内部包含了智能数字接口数据锁存信号整形放大驱动电路和高精度内部振荡器外,还采用了单线归零码的通讯方式:每个WS2812在上电复位以后,DIN端接收从控制器传输过来的数据,首先送过来的24bit数据被第一个WS2812提取后,送到其内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的WS2812,每经过一个WS2812的传输,信号减少24bit。每个WS2812采用自动整形转发技术,使得该WS2812的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。     采用这种通信方式的好处是大大节约了单片机管脚资源。例如做一个流水灯,如果采用传统的LED一般情况需要跟LED数量相同的单片机引脚(想想就心疼),但是使用WS2812就不一样了,一个单片机引脚就可以控制百级数量的灯带,而且还是全彩的,是不是感觉很神奇,很方便。由于WS2812采用单线的通信方式,其通过不同的脉冲长度来表示。
艰默
2022/11/22
1.8K0
Arduino配置WS2812及Adafruit_NeoPixel库的使用
[oeasy]python0104_指示灯_显示_LED_辉光管_霓虹灯
编码进化 回忆上次内容 x86、arm、riscv等基础架构 都是二进制的 包括各种数据、指令 但是我们接触到的东西 都是屏幕显示出来的字符 计算机 显示出来的 一个个具体的字型 ​ 计算机中用来展示的字型 究竟是 如何进化的 呢?🤔🤔 模拟电路时代 电压表、示波器 都是 输出设备 ​ 甚至可以 用来 玩游戏 当时用什么 输入输出呢? 输入输出(io) 最基本的 输入设备(input) 是 电键 (key) 输入 0或1 ​ 最基本的输出是什么呢? 基
oeasy
2023/03/09
3440
[oeasy]python0104_指示灯_显示_LED_辉光管_霓虹灯
太阳能火焰灯玉米灯ic方案 RGB方案
太阳光是人类生存不可或缺的能源之一,而太阳能则是一种清洁、可再生的能源。随着人们对环保和能源利用的不断探索,太阳能的应用也越来越广泛。太阳能火焰灯玉米灯是一种集成了太阳能电池板、LED灯珠和IC控制器的户外照明设备,具有安全、环保、实用、美观等特点,被广泛应用于公园、广场、庭院等场所。
泛海微电
2023/11/24
1520
《安富莱嵌入式周报》第300期:几百种炫酷灯阵玩法, USB Web网页固件升级,波士顿动力整活,并联二极管问题,VisualStudio升级,STM32C0
往期周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 祝大家春节快乐 视
Simon223
2023/02/23
4560
《安富莱嵌入式周报》第300期:几百种炫酷灯阵玩法,  USB Web网页固件升级,波士顿动力整活,并联二极管问题,VisualStudio升级,STM32C0
物联网-GPIO输出—使用固件库点亮LED灯
本实验板连接了 3 个 LED 灯,这些 LED 灯的阴极都是连接到 STM32 的 GPIO 引脚, 只要我们控制 GPIO 引脚的电平输出状态,即可控制 LED 灯的亮灭。 若您使用的实验板 LED 灯的连接方式或引脚不一样,只需根据我们的工程修改引脚即可,程序的控制原理相同。
会洗碗的CV工程师
2024/02/05
3040
物联网-GPIO输出—使用固件库点亮LED灯
没错,单片机写出那些你没点过的灯
很多初学者都觉得自己学的东西很基础,担心今后实际工作用不到。于是,有初学者提出这样的问题:单片机真正开发产品和学习的时候有什么差别?平时学的LED、ADC这些东西,在实际项目中会用到吗?
单片机技术宅
2022/11/22
6080
没错,单片机写出那些你没点过的灯
蓝牙串口通信控制Arduino全彩呼吸灯
HC-05 VCC ----- Arduino VIN HC-05 GND ----- Arduino GND HC-05 TXD ----- Arduino RXD HC-05 RXD ----- Arduino TXD
小雨coding
2020/06/09
2K0
蓝牙串口通信控制Arduino全彩呼吸灯
机器人控制器编程实践指导书旧版-实践一 LED灯(数字量)
适用于UNO/2560/DUE/ESP8266/ESP32,2021年之前使用版本。
zhangrelay
2022/08/10
1.1K0
机器人控制器编程实践指导书旧版-实践一 LED灯(数字量)
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项!
「ximagine」在本篇文章中将介绍「荒岛」目前所使用的显示器测试流程及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,当然这不是唯一的选择,还可以使用尊正Colourspace或者Admesy Prometheus以及积分球软件设备等。我们深知做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,当然我们的也有用大白话让大家都看明白的优势。总的来说是测试设备分为色度计和分光光度计两种类型,色度计使用RGB三色滤色片获取光谱数据,但在同色异谱方面,因为只能获取RGB滤色的结果,所以无法识别同色异谱等现象,分光光度计使用31块滤色镜或者光栅获取全光谱的数据。测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进。如果本内容对您有所帮助,麻烦三连支持一下,十分感谢。网上冲浪久了,键盘侠见的也就多了;他们不仅自己不行,还质疑你不行。
ximagine
2025/02/12
2420
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项!
使用文心一言等智能工具指数级提升嵌入式/物联网(M5Atom/ESP32)和机器人操作系统(ROS1/ROS2)学习研究和开发效率
嵌入式通常就是接口IO,input/output,对应于机器人操作系统, 升级了名字,交互,pub/sub。
zhangrelay
2023/08/02
3000
使用文心一言等智能工具指数级提升嵌入式/物联网(M5Atom/ESP32)和机器人操作系统(ROS1/ROS2)学习研究和开发效率
ESP8266_07基于PWM的呼吸灯
ESP8266系统的PWM( Pulse Width Modulation)由FRC1在软件上实现,可实现同频
MCU起航
2020/06/29
1.2K0
[IoT迷你赛]基于TencentOS tiny的SmartLight小工具
本项目基于TencentOS tiny(腾讯物联网操作系统)构建了一款智能灯小工具产品。整个产品架构上分为硬件底层、云平台层和小程序终端层,利用官方的Demo框架可迅速打通三层的基本通信逻辑,再对相应接口的调用及方法改写便可创作出自己需要的产品项目来,这也是本项目的构建思路,下面开始详细介绍。
梦to鑫
2019/08/28
1.8K0
[IoT迷你赛]基于TencentOS tiny的SmartLight小工具
大规模 RGB LED灯控系统 Lumos:创新与智能化的融合
在现代照明技术不断进步的背景下,灯控系统的应用已经从简单的开关控制,发展到能够进行复杂程控操作的智能化管理。我们推出的新一代灯控解决方案,凭借其高度的可配置性和跨平台兼容性,已成为多种商业及娱乐场合的首选。
拿我格子衫来
2024/05/25
3630
大规模 RGB LED灯控系统 Lumos:创新与智能化的融合
基于STM32设计的智能插座+人体感应灯(ESP8266+人体感应+手机APP)
手机APP: 采用QT设计,程序支持跨平台编译运行(Android、IOS、Windows、Linux都可以编译运行,对应平台上QT的环境搭建,之前博客已经发了文章讲解)
DS小龙哥
2022/01/12
2.8K0
基于STM32设计的智能插座+人体感应灯(ESP8266+人体感应+手机APP)
树莓派基础实验3:七彩LED灯闪烁实验
   七彩LED灯上电后,7色自动闪光LED模块可自动闪烁内置颜色。可以用来制作相当迷人的灯光效果。
张国平
2020/09/28
1.8K0
树莓派基础实验3:七彩LED灯闪烁实验
推荐阅读
DJI TT无人机 microPython编程指南
1.7K0
eps32和ros2之稳稳点亮一个LED灯(IO4)
5340
涵盖 Java 核心知识的综合指南:JavaGuide | 开源日报 0912
3170
用安信可Ai-WB2-01S做一个可用网页控制的简易灯
590
利用esp8266做一个物联网小灯
1K0
Arduino配置WS2812及Adafruit_NeoPixel库的使用
1.8K0
[oeasy]python0104_指示灯_显示_LED_辉光管_霓虹灯
3440
太阳能火焰灯玉米灯ic方案 RGB方案
1520
《安富莱嵌入式周报》第300期:几百种炫酷灯阵玩法, USB Web网页固件升级,波士顿动力整活,并联二极管问题,VisualStudio升级,STM32C0
4560
物联网-GPIO输出—使用固件库点亮LED灯
3040
没错,单片机写出那些你没点过的灯
6080
蓝牙串口通信控制Arduino全彩呼吸灯
2K0
机器人控制器编程实践指导书旧版-实践一 LED灯(数字量)
1.1K0
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项!
2420
使用文心一言等智能工具指数级提升嵌入式/物联网(M5Atom/ESP32)和机器人操作系统(ROS1/ROS2)学习研究和开发效率
3000
ESP8266_07基于PWM的呼吸灯
1.2K0
[IoT迷你赛]基于TencentOS tiny的SmartLight小工具
1.8K0
大规模 RGB LED灯控系统 Lumos:创新与智能化的融合
3630
基于STM32设计的智能插座+人体感应灯(ESP8266+人体感应+手机APP)
2.8K0
树莓派基础实验3:七彩LED灯闪烁实验
1.8K0
相关推荐
DJI TT无人机 microPython编程指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档