TensorFlow 1.x 深度学习秘籍:6~10(2)

简介: TensorFlow 1.x 深度学习秘籍:6~10(2)

TensorFlow 1.x 深度学习秘籍:6~10(1)https://developer.aliyun.com/article/1426770

操作步骤

让我们从秘籍开始:

  1. 与往常一样,第一步是导入模块。 在这种情况下,除了通常的模块之外,我们还将导入gym,以便我们可以使用它提供的不同环境:
import gym
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
  1. 接下来,我们创建一个RlAgent类。 该类由三种方法组成-__init__方法初始化 NN 大小并创建计算图。 在这里,我们使用了 TensorFlow 函数tf.multinomial来决定采取的可能措施。 该函数根据我们网络的 9 个输出神经元的 Sigmoid 值返回操作。 这样可以确保网络根据概率选择最终操作。 predict方法返回由 NN 预测的动作。 get_weights方法可帮助我们获得获胜者智能体的权重和偏置:
class RlAgent(object):
 def __init__(self,m,n,ini=False,W=None, b=None ):
     self._graph = tf.Graph()
     with self._graph.as_default():
     self._X = tf.placeholder(tf.float32,shape=(1,m))
     if ini==False:
         self.W = tf.Variable(tf.random_normal([m,n]), trainable=False)
         self.bias =         tf.Variable(tf.random_normal([1,n]),trainable=False)
     else:
         self.W = W
         self.bias = b
     out = tf.nn.sigmoid(tf.matmul(self._X,self.W)+ self.bias)
     self._result = tf.multinomial(out,1)
     init = tf.global_variables_initializer()
    self._sess = tf.Session()
    self._sess.run(init)
    def predict(self, X):
         action = self._sess.run(self._result, feed_dict= {self._X: X})
         return action
    def get_weights(self):
         W, b = self._sess.run([self.W, self.bias])
         return W, b
  1. 我们定义了一些辅助函数来玩一个完整的游戏play_one_episode
def play_one_episode(env, agent):
    obs = env.reset()
    img_pre = preprocess_image(obs)
     done = False
     t = 0
    while not done and t < 10000:
         env.render()  # This can be commented to speed up 
         t += 1
         action = agent.predict(img_pre)
         #print(t,action)
         obs, reward, done, info = env.step(action)
         img_pre = preprocess_image(obs)
         if done:
             break
    return t
  1. play_multiple_episodes函数创建智能体的一个实例,并使用该智能体进行许多游戏,并返回其平均游戏时间:
def play_multiple_episodes(env, T,ini=False, W=None, b=None):
    episode_lengths = np.empty(T)
    obs = env.reset()
    img_pre = preprocess_image(obs)
    if ini== False:
        agent = RlAgent(img_pre.shape[1],env.action_space.n)
    else:
        agent = RlAgent(img_pre.shape[1],env.action_space.n,ini, W, b)
    for i in range(T):
        episode_lengths[i] = play_one_episode(env, agent)
    avg_length = episode_lengths.mean()
    print("avg length:", avg_length)
    if ini == False:
        W, b = agent.get_weights()
    return avg_length, W, b
  1. random_search函数调用play_multiple_episodes; 每次调用play_multiple_episodes时,都会使用一组新的随机权重和偏差来实例化新智能体。 这些随机创建的 NN 智能体之一将胜过其他智能体,这将是我们最终选择的智能体:
def random_search(env):
    episode_lengths = []
    best = 0
    for t in range(10):
        print("Agent {} reporting".format(t))
        avg_length, wts, bias = play_multiple_episodes(env, 10)
        episode_lengths.append(avg_length)
        if avg_length > best:
            best_wt = wts
            best_bias = bias
            best = avg_length
    return episode_lengths, best_wt, best_bias
  1. 每次执行步骤时,环境都会返回一个观察场。 该观察具有三个颜色通道。 为了将其馈送到 NN,需要对观测值进行预处理,目前,我们唯一要做的预处理是将其转换为灰度,增加对比度并将其整形为行向量:
def preprocess_image(img):
    img = img.mean(axis =2) # to grayscale
    img[img==150] = 0  # Bring about a better contrast
    img = (img - 128)/128 - 1 # Normalize image from -1 to 1
    m,n = img.shape
    return img.reshape(1,m*n)
  1. NN 智能体一一实例化,然后选择最佳智能体。 为了提高计算效率,我们目前仅搜索 10 个智能体,每个智能体玩 10 场比赛。 玩得最长的游戏被认为是最好的:
if __name__ == '__main__':
    env_name = 'Breakout-v0'
    #env_name = 'MsPacman-v0'
    env = gym.make(env_name)
    episode_lengths, W, b = random_search(env)
    plt.plot(episode_lengths)
    plt.show()
    print("Final Run with best Agent")
    play_multiple_episodes(env,10, ini=True, W=W, b=b)

结果如下:

我们可以看到我们的随机智能体也可以平均 615.5 的长度玩游戏。 不错!

用 Q 学习平衡推车

如导言所述,我们有一个由状态ss ∈ S,其中S是所有可能状态的集合)描述的环境,可以执行动作aa ∈ A,其中A由所有可能的动作组成),从而导致主体从一种状态移动到另一种状态 。 智能体因其行为而受到奖励,智能体的目标是使奖励最大化。 在 Q 学习中,智能体通过计算最大化报酬的状态-动作组合的数量(R)来学习要采取的动作(策略,π)。 在选择行动时,智能体不仅要考虑现在的奖励,而且要考虑未来的折扣。

Q: S × A → R

智能体以Q的任意初始值开头,并且随着智能体选择动作a并获得奖励r,它会更新状态s(取决于过去状态s和动作a)和Q值:

Q(s, a) = (1 - α) · Q(s, a) + α(r + γ · max[a']Q(s', a'))

在此,α是学习率,γ是折扣因子。 第一项保留Q的旧值,第二项提供Q值的改进估计值(它包括当前奖励和未来行动的折现奖励)。 当结果状态不理想时,这将降低Q值,从而确保智能体在下次遇到此状态时不会选择相同的动作。 类似地,当期望结果状态时,相应的Q值将增加。

Q 学习的最简单实现涉及维护和更新状态-作用值查找表; 表的大小将为N×M,其中N是所有可能状态的数量,M是所有可能动作的数量。 对于大多数环境,此表将很大。 表越大,搜索所需的时间就越多,并且存储表所需的内存也就越多,因此这不是可行的解决方案。 在本秘籍中,我们将使用 Q 学习的 NN 实现。 在此,将神经网络用作函数逼近器来预测值函数(Q)。 NN 具有等于可能动作数的输出节点,并且它们的输出表示相应动作的值函数。

准备

我们将训练一个线性神经网络来解决'CartPole-v0'环境。 目的是平衡手推车上的杆。 观测状态由四个连续值参数组成:推车位置[-2.4, 2.4],推车速度[-∞, ∞],极角[~-41.8º, ~41.8º]和极限速度[-∞, ∞]。 可以通过向左或向右推推车来实现平衡,因此动作空间由两个可能的动作组成。 您可以看到CartPole-v0环境空间:

现在,对于 Q 学习,我们需要找到一种量化连续值观测状态的方法。 这是使用类FeatureTransform实现的; 该类首先生成 20,000 个观察空间示例的随机样本。 随机生成的观察空间示例使用 scikit StandardScaler类进行了标准化。 然后以不同的方差使用 scikit 的RBFSampler来覆盖观察空间的不同部分。 FeatureTransformer类由随机观察空间示例实例化,该示例用于使用fit_transform函数方法训练RBFSampler

后来,使用transform方法将连续观察空间转换为这种特征化表示:

class FeatureTransformer:
 def __init__(self, env):
   obs_examples = np.random.random((20000, 4))
   print(obs_examples.shape)
   scaler = StandardScaler()
   scaler.fit(obs_examples)
   # Used to converte a state to a featurizes represenation.
   # We use RBF kernels with different variances to cover different parts of the space
   featurizer = FeatureUnion([
       ("cart_position", RBFSampler(gamma=0.02, n_components=500)),
       ("cart_velocity", RBFSampler(gamma=1.0, n_components=500)),
       ("pole_angle", RBFSampler(gamma=0.5, n_components=500)),
       ("pole_velocity", RBFSampler(gamma=0.1, n_components=500))
       ])
    feature_examples =          featurizer.fit_transform(scaler.transform(obs_examples))
    print(feature_examples.shape)
    self.dimensions = feature_examples.shape[1]
    self.scaler = scaler
    self.featurizer = featurizer
def transform(self, observations):
    scaled = self.scaler.transform(observations)
    return self.featurizer.transform(scaled)

操作步骤

我们按以下步骤进行:

  1. 第一步是导入必要的模块。 这次,除了我们通常的 TensorFlow,Numpy 和 Matplotlib,我们还将从 scikit 导入 Gym 和一些类:
import numpy as np
import tensorflow as tf
import gym
import matplotlib.pyplot as plt
from sklearn.pipeline import FeatureUnion
from sklearn.preprocessing import StandardScaler
from sklearn.kernel_approximation import RBFSampler
  1. 在 Q 学习中,我们使用 NN 作为函数逼近器来估计值函数。 我们定义一个线性NeuralNetwork类; NN 将把变换后的观测空间作为输入并预测估计的Q值。 由于我们有两个可能的动作,因此我们需要两个不同的神经网络对象来获取预测的状态动作值。 该类包括训练单个 NN 和预测输出的方法:
class NeuralNetwork:
 def __init__(self, D):
     eta = 0.1
     self.W = tf.Variable(tf.random_normal(shape=(D, 1)), name='w')
     self.X = tf.placeholder(tf.float32, shape=(None, D), name='X')
     self.Y = tf.placeholder(tf.float32, shape=(None,), name='Y')
     # make prediction and cost
     Y_hat = tf.reshape(tf.matmul(self.X, self.W), [-1])
     err = self.Y - Y_hat
     cost = tf.reduce_sum(tf.pow(err,2))
    # ops we want to call later
    self.train_op = tf.train.GradientDescentOptimizer(eta).minimize(cost)
    self.predict_op = Y_hat
    # start the session and initialize params
    init = tf.global_variables_initializer()
    self.session = tf.Session()
    self.session.run(init)
def train(self, X, Y):
    self.session.run(self.train_op, feed_dict={self.X: X, self.Y: Y})
def predict(self, X):
    return self.session.run(self.predict_op, feed_dict={self.X: X})
  1. 下一个重要的类是Agent类,它使用NeuralNetwork类来创建学习智能体。 实例化类创建具有两个线性 NN 的智能体,每个线性 NN 具有 2,000 个输入神经元和 1 个输出神经元。 (从本质上讲,这意味着该智能体具有 2 个神经元,每个神经元具有 2,000 个输入,因为 NN 的输入层不执行任何处理)。 Agent类具有定义为预测两个 NN 的输出并更新两个 NN 权重的方法。 此处的智能体在训练阶段使用 Epsilon 贪婪策略进行探索。 在每个步骤中,智能体程序会根据 epsilon(eps)的值选择具有最高Q值的操作或随机操作。 epsilon 在训练过程中经过退火处理,因此,最初,智能体会采取许多随机动作(探索),但随着训练的进行,会采取具有最大Q值的动作(探索)。 这称为探索与开发的权衡取舍:我们允许智能体在被利用的操作过程中探索随机操作,这使智能体可以尝试新的随机操作并从中学习:
class Agent:
 def __init__(self, env, feature_transformer):
 self.env = env
 self.agent = []
 self.feature_transformer = feature_transformer
 for i in range(env.action_space.n):
 model = NeuralNetwork(feature_transformer.dimensions)
 self.agent.append(model)
def predict(self, s):
 X = self.feature_transformer.transform([s])
 return np.array([m.predict(X)[0] for m in self.agent])
def update(self, s, a, G):
 X = self.feature_transformer.transform([s])
 self.agent[a].train(X, [G])
def sample_action(self, s, eps):
 if np.random.random() < eps:
     return self.env.action_space.sample()
 else:
     return np.argmax(self.predict(s))
  1. 接下来,我们定义一个函数来播放一集; 它类似于我们先前使用的play_one函数,但现在我们使用 Q 学习来更新智能体的权重。 我们首先使用env.reset()重置环境,然后开始游戏,直到完成游戏为止(并进行了最大迭代以确保程序结束)。 像以前一样,智能体为当前观察状态选择一个动作,并在环境上执行该动作(env.step(action))。 现在的区别在于,根据先前状态和采取操作后的状态,使用G = r + γ · max[a']Q(s', a')更新 NN 权重,以便它可以预测与某个动作相对应的准确期望值。 为了获得更好的稳定性,我们修改了奖励-杆位下降时,座席会获得 -400 的奖励,否则,每一步都会获得 +1 的奖励:
def play_one(env, model, eps, gamma):
 obs = env.reset()
 done = False
 totalreward = 0
 iters = 0
 while not done and iters < 2000:
 action = model.sample_action(obs, eps)
 prev_obs = obs
 obs, reward, done, info = env.step(action)
 env.render()   # Can comment it to speed up.
if done:
 reward = -400
# update the model
 next = model.predict(obs)
 assert(len(next.shape) == 1)
 G = reward + gamma*np.max(next)
 model.update(prev_obs, action, G)
if reward == 1:
 totalreward += reward
iters += 1
  1. 现在所有函数和类均已就绪,我们定义了智能体和环境(在本例中为'CartPole-v0')。 该智能体总共播放 1000 集,并通过使用值函数与环境交互来学习:
if __name__ == '__main__':
    env_name = 'CartPole-v0'
    env = gym.make(env_name)
    ft = FeatureTransformer(env)
    agent = Agent(env, ft)
    gamma = 0.97
    N = 1000
    totalrewards = np.empty(N)
    running_avg = np.empty(N)
    for n in range(N):
        eps = 1.0 / np.sqrt(n + 1)
        totalreward = play_one(env, agent, eps, gamma)
        totalrewards[n] = totalreward
        running_avg[n] = totalrewards[max(0, n - 100):(n + 1)].mean()
        if n % 100 == 0:
            print("episode: {0}, total reward: {1} eps: {2} avg reward (last 100): {3}".format(n, totalreward, eps,
                                                                                               running_avg[n]), )
    print("avg reward for last 100 episodes:", totalrewards[-100:].mean())
    print("total steps:", totalrewards.sum())
    plt.plot(totalrewards)
    plt.xlabel('episodes')
    plt.ylabel('Total Rewards')
    plt.show()
    plt.plot(running_avg)
    plt.xlabel('episodes')
    plt.ylabel('Running Average')
    plt.show()
    env.close()

  1. 以下是智能体通过游戏获悉的总奖励和移动平均奖励的图。 根据 Cart-Pole Wiki 的说法,奖励 200 分表示该特工在接受 1,000 次训练后赢得了该剧集。 我们的特工播放 100 集时平均获得 195.7 的平均奖励,这是一项了不起的壮举:

更多

可以使用相同的逻辑为 OpenAI 的其他环境创建智能体。 但是,对于诸如 Breakout 或 Pac-Man 之类的 Atari 游戏,观察空间并不只是由四个数字组成的数组。 相反,它非常大(210×160 = 33,600 像素,具有 3 个 RGB 值); 如果没有某种形式的量化,则这种简单的 NN 可能的状态是无限的,并且不会产生良好的结果。 我们将在深度 Q 学习秘籍中使用 CNN 解决此问题。

另见

尽管有很多有关 Q 学习的 Web 链接,但一些有用的链接如下:

深度 Q 网络和 Atari 游戏

深度 Q 网络DQN)是 Q 学习与卷积神经网络CNN)的结合。 由 Mnih 等人在 2013 年提出。 CNN 网络具有提取空间信息的能力,因此能够从原始像素数据中学习成功的控制策略。 我们已经在第 4 章,“卷积神经网络”中使用了 CNN,因此我们直接从这里开始。

此秘籍基于 DeepMind 的原始 DQN 论文《使用深度强化学习玩 Atari》。 在本文中,他们使用了一种称为“经验重放”的概念,该概念涉及随机采样先前的游戏动作(状态,动作奖励,下一状态)。位于前脑底部的核称为“基底神经节”, 根据神经科学,它们负责选择动作,即帮助我们确定在任何给定时间执行几种可能动作中的哪一种。

准备

如先前的秘籍所述,“用 Q 学习平衡 CartPole”,对于像《吃豆人》或 Breakout 之类的 Atari 游戏,我们需要预处理观察状态空间,该状态空间由 33,600 个像素组成,具有 3 个 RGB 值。 这些像素中的每个像素都可以采用 0 到 255 之间的任何值。我们的preprocess函数应该能够量化像素的可能值,同时减少观察状态空间。

我们利用 Scipy 的imresize函数对图像进行下采样。 以下函数preprocess在将图像馈送到 DQN 之前:

def preprocess(img):
    img_temp = img[31:195]  # Choose the important area of the image
    img_temp = img_temp.mean(axis=2)  # Convert to Grayscale#
    # Downsample image using nearest neighbour interpolation
    img_temp = imresize(img_temp, size=(IM_SIZE, IM_SIZE), interp='nearest')
    return img_temp

IM_SIZE是一个全局参数-在代码中,我们将其值为 80。该函数具有描述每个过程的注释。 在这里,您可以看到预处理前后的观察空间:

要注意的另一重要事项是,当前的观察空间不能完全显示游戏情况。 例如,参见上图,您无法确定桨叶是向左还是向右移动。 因此,为了完全理解游戏的当前状态,我们需要考虑动作和观察的顺序。 在秘籍中,我们考虑了四个动作和观察序列,以确定当前情况并训练智能体。 这是借助state_update函数完成的,该函数将当前的观察状态附加到先前的状态,从而生成一系列状态:

def update_state(state, obs):
    obs_small = preprocess(obs)
    return np.append(state[1:], np.expand_dims(obs_small, 0), axis=0)

最后,为了解决训练时的稳定性问题,我们使用了target_network的概念,它是 DQN 的副本,但更新频率不高。 我们使用目标网络来生成 DQN 网络的目标值函数,而 DQN 在每个步骤/片段都进行更新,并且target_network在固定间隔后进行更新(与 DQN 相同)。 由于所有更新都在 TensorFlow 会话中进行,因此我们使用名称范围来区分target_network和 DQN 网络。

操作步骤

  1. 我们导入必要的模块。 我们正在使用sys模块的stdout.flush()来帮助我们强制 Python 刷新标准输出(在我们的情况下为计算机监视器)中的数据。 random模块用于从经验重放缓冲区(我们存储过去经验的缓冲区)中获取随机样本。 datetime模块用于跟踪训练时间:
import gym
import sys
import random
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from datetime import datetime
from scipy.misc import imresize
  1. 我们定义训练的超参数; 您可以通过更改它们进行试验。 这些参数定义了经验重放缓冲区的最小和最大大小以及更新目标网络之后的情节数量:
MAX_EXPERIENCES = 500000
MIN_EXPERIENCES = 50000
TARGET_UPDATE_PERIOD = 10000
IM_SIZE = 80
K = 4
  1. 定义了类DQN; 其构造器使用tf.contrib.layers.conv2d函数构建 CNN 网络,并定义成本和训练操作:
class DQN:
    def __init__(self, K, scope, save_path= 'models/atari.ckpt'):
        self.K = K
        self.scope = scope
        self.save_path = save_path
        with tf.variable_scope(scope):
            # inputs and targets
            self.X = tf.placeholder(tf.float32, shape=(None, 4, IM_SIZE, IM_SIZE), name='X')
            # tensorflow convolution needs the order to be:
            # (num_samples, height, width, "color")
            # so we need to tranpose later
            self.G = tf.placeholder(tf.float32, shape=(None,), name='G')
            self.actions = tf.placeholder(tf.int32, shape=(None,), name='actions')
            # calculate output and cost
            # convolutional layers
            Z = self.X / 255.0
            Z = tf.transpose(Z, [0, 2, 3, 1])
            cnn1 = tf.contrib.layers.conv2d(Z, 32, 8, 4, activation_fn=tf.nn.relu)
            cnn2 = tf.contrib.layers.conv2d(cnn1, 64, 4, 2, activation_fn=tf.nn.relu)
            cnn3 = tf.contrib.layers.conv2d(cnn2, 64, 3, 1, activation_fn=tf.nn.relu)
            # fully connected layers
            fc0 = tf.contrib.layers.flatten(cnn3)
            fc1 = tf.contrib.layers.fully_connected(fc0, 512)
            # final output layer
            self.predict_op = tf.contrib.layers.fully_connected(fc1, K)
            selected_action_values = tf.reduce_sum(self.predict_op * tf.one_hot(self.actions, K),
                reduction_indices=[1]
            )
            self.cost = tf.reduce_mean(tf.square(self.G - selected_action_values))
            self.train_op = tf.train.RMSPropOptimizer(0.00025, 0.99, 0.0, 1e-6).minimize(self.cost)
  1. 该类具有设置会话set_session(),预测动作值函数predict(),更新网络update()以及使用 Epsilon 贪婪算法sample_action()选择动作的方法:
def set_session(self, session):
    self.session = session
def predict(self, states):
    return self.session.run(self.predict_op, feed_dict={self.X: states})
def update(self, states, actions, targets):
    c, _ = self.session.run(
        [self.cost, self.train_op],
        feed_dict={
            self.X: states,
            self.G: targets,
            self.actions: actions
        }
    )
    return c
def sample_action(self, x, eps):
    """Implements epsilon greedy algorithm"""
    if np.random.random() < eps:
        return np.random.choice(self.K)
    else:
        return np.argmax(self.predict([x])[0])
  1. 我们还定义了加载和保存网络的方法,因为训练可能会花费一些时间:
def load(self):
    self.saver = tf.train.Saver(tf.global_variables())
    load_was_success = True
    try:
        save_dir = '/'.join(self.save_path.split('/')[:-1])
        ckpt = tf.train.get_checkpoint_state(save_dir)
        load_path = ckpt.model_checkpoint_path
        self.saver.restore(self.session, load_path)
    except:
        print("no saved model to load. starting new session")
        load_was_success = False
    else:
        print("loaded model: {}".format(load_path))
        saver = tf.train.Saver(tf.global_variables())
        episode_number = int(load_path.split('-')[-1])
def save(self, n):
    self.saver.save(self.session, self.save_path, global_step=n)
    print("SAVED MODEL #{}".format(n))
  1. 将主 DQN 网络的参数复制到目标网络的方法如下:
def copy_from(self, other):
    mine = [t for t in tf.trainable_variables() if t.name.startswith(self.scope)]
    mine = sorted(mine, key=lambda v: v.name)
    others = [t for t in tf.trainable_variables() if t.name.startswith(other.scope)]
    others = sorted(others, key=lambda v: v.name)
    ops = []
    for p, q in zip(mine, others):
        actual = self.session.run(q)
        op = p.assign(actual)
        ops.append(op)
    self.session.run(ops)
  1. 我们定义一个函数learn(),它预测值函数并更新原始 DQN 网络:
def learn(model, target_model, experience_replay_buffer, gamma, batch_size):
    # Sample experiences
    samples = random.sample(experience_replay_buffer, batch_size)
    states, actions, rewards, next_states, dones = map(np.array, zip(*samples))
    # Calculate targets
    next_Qs = target_model.predict(next_states)
    next_Q = np.amax(next_Qs, axis=1)
    targets = rewards + np.invert(dones).astype(np.float32) * gamma * next_Q
    # Update model
    loss = model.update(states, actions, targets)
    return loss
  1. 既然我们已经在主代码中定义了所有特征,我们就可以使用它们来构建和训练 DQN 网络以玩 Atari 游戏。 该代码经过了很好的注释,并且是对先前 Q 学习代码的扩展,并增加了经验重放缓冲区,因此您应该不难理解它:
if __name__ == '__main__':
    # hyperparameters
    gamma = 0.99
    batch_sz = 32
    num_episodes = 500
    total_t = 0
    experience_replay_buffer = []
    episode_rewards = np.zeros(num_episodes)
    last_100_avgs = []
    # epsilon for Epsilon Greedy Algorithm
    epsilon = 1.0
    epsilon_min = 0.1
    epsilon_change = (epsilon - epsilon_min) / 500000
    # Create Atari Environment
    env = gym.envs.make("Breakout-v0")
    # Create original and target  Networks
    model = DQN(K=K, gamma=gamma, scope="model")
    target_model = DQN(K=K, gamma=gamma, scope="target_model")
    with tf.Session() as sess:
        model.set_session(sess)
        target_model.set_session(sess)
        sess.run(tf.global_variables_initializer())
        model.load()
        print("Filling experience replay buffer...")
        obs = env.reset()
        obs_small = preprocess(obs)
        state = np.stack([obs_small] * 4, axis=0)
        # Fill experience replay buffer
        for i in range(MIN_EXPERIENCES):
            action = np.random.randint(0,K)
            obs, reward, done, _ = env.step(action)
            next_state = update_state(state, obs)
            experience_replay_buffer.append((state, action, reward, next_state, done))
            if done:
                obs = env.reset()
                obs_small = preprocess(obs)
                state = np.stack([obs_small] * 4, axis=0)
            else:
                state = next_state
        # Play a number of episodes and learn
        for i in range(num_episodes):
            t0 = datetime.now()
            # Reset the environment
            obs = env.reset()
            obs_small = preprocess(obs)
            state = np.stack([obs_small] * 4, axis=0)
            assert (state.shape == (4, 80, 80))
            loss = None
            total_time_training = 0
            num_steps_in_episode = 0
            episode_reward = 0
            done = False
            while not done:
                # Update target network
                if total_t % TARGET_UPDATE_PERIOD == 0:
                    target_model.copy_from(model)
                    print("Copied model parameters to target network. total_t = %s, period = %s" % (
                        total_t, TARGET_UPDATE_PERIOD))
                # Take action
                action = model.sample_action(state, epsilon)
                obs, reward, done, _ = env.step(action)
                obs_small = preprocess(obs)
                next_state = np.append(state[1:], np.expand_dims(obs_small, 0), axis=0)
                episode_reward += reward
                # Remove oldest experience if replay buffer is full
                if len(experience_replay_buffer) == MAX_EXPERIENCES:
                    experience_replay_buffer.pop(0)
                # Save the recent experience
                experience_replay_buffer.append((state, action, reward, next_state, done))
                # Train the model and keep measure of time
                t0_2 = datetime.now()
                loss = learn(model, target_model, experience_replay_buffer, gamma, batch_sz)
                dt = datetime.now() - t0_2
                total_time_training += dt.total_seconds()
                num_steps_in_episode += 1
                state = next_state
                total_t += 1
                epsilon = max(epsilon - epsilon_change, epsilon_min)
            duration = datetime.now() - t0
            episode_rewards[i] = episode_reward
            time_per_step = total_time_training / num_steps_in_episode
            last_100_avg = episode_rewards[max(0, i - 100):i + 1].mean()
            last_100_avgs.append(last_100_avg)
            print("Episode:", i,"Duration:", duration, "Num steps:", num_steps_in_episode,
                  "Reward:", episode_reward, "Training time per step:", "%.3f" % time_per_step,
                  "Avg Reward (Last 100):", "%.3f" % last_100_avg,"Epsilon:", "%.3f" % epsilon)
            if i % 50 == 0:
                model.save(i)
            sys.stdout.flush()
    #Plots
    plt.plot(last_100_avgs)
    plt.xlabel('episodes')
    plt.ylabel('Average Rewards')
    plt.show()
    env.close()

从上图中我们可以看到,特工通过训练获得了更高的报酬,并且通过每 100 集的平均报酬图可以清楚地看到情况:

这只是在训练的前 500 集之后; 为了获得更好的效果,您将需要训练更长的时间,约 10,000 集。

更多

训练智能体需要花费很多时间,这既浪费时间又消耗内存。 OpenAI Gym 提供了一个包装器来将游戏另存为视频,因此,除了使用渲染之外,您还可以使用包装器来保存视频并随后监视智能体的学习方式。 AI 工程师和发烧友可以上传这些视频以显示结果。 为此,我们需要首先导入包装器,然后创建环境,最后使用监视器。 默认情况下,它将存储 1、8、27、64 等视频,然后每第 1000 集(带有完美立方体的情节编号)存储; 默认情况下,每项训练都保存在一个文件夹中。 为此要添加的代码如下:

import gym
from gym import wrappers
env = gym.make('Breakout-v0)
env = wrappers.Monitor(env, '/save-path')

如果您想在下一个训练中使用相同的文件夹,可以将force=True添加到监视器。

另见

  • Mnih, Volodymyr, and others, Playing Atari with deep reinforcement learning, arXiv preprint arXiv:1312.5602 (2013) (https://arxiv.org/pdf/1312.5602.pdf)
  • Mnih, Volodymyr, et al. Human-level control through deep reinforcement learning, Nature 518.7540 (2015): 529-533
  • 玩 Atari 的 DQN 的一个很酷的实现

使用策略梯度玩 Pong 游戏

到目前为止,策略梯度是最常用的 RL 算法之一。 研究表明,经过适当调优后,它们的表现要优于 DQN,同时不会遭受过多的内存和计算缺点。 与 Q 学习不同,策略梯度使用参数化策略,该策略可以选择操作而不咨询值函数。 在策略梯度中,我们讨论了表现度量η(θ[p]); 目标是最大程度地提高表现,因此根据梯度上升算法更新 NN 的权重。 但是,TensorFlow 没有maximum优化器,因此我们使用表现梯度的负值-∇η(θ[p])并将其最小化。

准备

Pong 的游戏是一个两人游戏,目标是将球弹回另一位玩家。 智能体可以上下移动操纵杆(是的,是标准NoOp)。 OpenAI 环境中的一名玩家是一位体面的 AI 玩家,他知道如何很好地玩游戏。 我们的目标是使用策略梯度来训练第二个智能体。 我们的经纪人精通所玩的每款游戏。 虽然代码已构建为只能运行 500 集,但我们应该添加一条规定以将智能体状态保存在指定的检查点,并且在下一次运行时,首先加载上一个检查点。 为此,我们首先声明一个保护程序,然后使用 TensorFlow saver.save方法保存当前的网络状态(检查点),最后从最后保存的检查点加载网络。 为完成本秘籍的部分,在“操作步骤”一节中定义的以下PolicyNetwork类方法可以执行此工作:

def load(self):
    self.saver = tf.train.Saver(tf.global_variables())
    load_was_success = True  # yes, I'm being optimistic
    try:
        save_dir = '/'.join(self.save_path.split('/')[:-1])
        ckpt = tf.train.get_checkpoint_state(save_dir)
        load_path = ckpt.model_checkpoint_path
        self.saver.restore(self.session, load_path)
    except:
        print("no saved model to load. starting new session")
        load_was_success = False
    else:
        print("loaded model: {}".format(load_path))
        saver = tf.train.Saver(tf.global_variables())
        episode_number = int(load_path.split('-')[-1])

为了每 50 集保存一次模型,我们使用以下方法:

def save(self):
    self.saver.save(self.session, self.save_path, global_step=n)
    print("SAVED MODEL #{}".format(n))

操作步骤

  1. 此秘籍的代码基于 Andrej Karpathy 博客,并且其中一部分已由 Sam Greydanus 的代码进行了改编。
  2. 我们有通常的导入:
import numpy as np
import gym
import matplotlib.pyplot as plt
import tensorflow as tf
  1. 我们定义我们的PolicyNetwork类。 在类构建期间,还将初始化模型超参数。 __init__方法定义输入状态self.tf_x的占位符; 预测作用,self.tf.y; 相应的奖励,self.tf_epr; 网络权重; 并预测行动值,训练和更新。 您可以看到该类构造还启动了一个交互式 TensorFlow 会话:
class PolicyNetwork(object):
    def __init__(self, N_SIZE, h=200, gamma=0.99, eta=1e-3, decay=0.99, save_path = 'models2/pong.ckpt' ):
        self.gamma = gamma
        self.save_path = save_path
        # Placeholders for passing state....
        self.tf_x = tf.placeholder(dtype=tf.float32, shape=[None, N_SIZE * N_SIZE], name="tf_x")
        self.tf_y = tf.placeholder(dtype=tf.float32, shape=[None, n_actions], name="tf_y")
        self.tf_epr = tf.placeholder(dtype=tf.float32, shape=[None, 1], name="tf_epr")
        # Weights
        xavier_l1 = tf.truncated_normal_initializer(mean=0, stddev=1\. / N_SIZE, dtype=tf.float32)
        self.W1 = tf.get_variable("W1", [N_SIZE * N_SIZE, h], initializer=xavier_l1)
        xavier_l2 = tf.truncated_normal_initializer(mean=0, stddev=1\. / np.sqrt(h), dtype=tf.float32)
        self.W2 = tf.get_variable("W2", [h, n_actions], initializer=xavier_l2)
        # Build Computation
        # tf reward processing (need tf_discounted_epr for policy gradient wizardry)
        tf_discounted_epr = self.tf_discount_rewards(self.tf_epr)
        tf_mean, tf_variance = tf.nn.moments(tf_discounted_epr, [0], shift=None, name="reward_moments")
        tf_discounted_epr -= tf_mean
        tf_discounted_epr /= tf.sqrt(tf_variance + 1e-6)
        # Define Optimizer, compute and apply gradients
        self.tf_aprob = self.tf_policy_forward(self.tf_x)
        loss = tf.nn.l2_loss(self.tf_y - self.tf_aprob)
        optimizer = tf.train.RMSPropOptimizer(eta, decay=decay)
        tf_grads = optimizer.compute_gradients(loss, var_list=tf.trainable_variables(), grad_loss=tf_discounted_epr)
        self.train_op = optimizer.apply_gradients(tf_grads)
        # Initialize Variables
        init = tf.global_variables_initializer()
        self.session = tf.InteractiveSession()
        self.session.run(init)
        self.load()
  1. 我们定义了一种计算折现奖励的方法。 这确保智能体不仅考虑当前奖励,而且考虑未来奖励。 任意时间t的折现奖励为R[t] = ∑γ[k]r[t + k],其中总和超过k∈[0, ∞],并且γ是贴现因子,值在 0 到 1 之间。在我们的代码中,我们使用了gamma = 0.99
def tf_discount_rewards(self, tf_r):  # tf_r ~ [game_steps,1]
    discount_f = lambda a, v: a * self.gamma + v;
    tf_r_reverse = tf.scan(discount_f, tf.reverse(tf_r, [0]))
    tf_discounted_r = tf.reverse(tf_r_reverse, [0])
    return tf_discounted_r
  1. 在给定输入观察状态的情况下,我们定义了tf_policy_forward方法来提供将桨向上移动的概率。 我们使用两层神经网络实现它。 网络获取处理过的游戏状态图像,并生成一个数字,表示将球拍向上移动的可能性。 在 TensorFlow 中,由于仅在 TensorFlow 会话中计算网络图,因此我们定义了另一种方法predict_UP来计算概率:
def tf_policy_forward(self, x): #x ~ [1,D]
     h = tf.matmul(x, self.W1)
     h = tf.nn.relu(h)
     logp = tf.matmul(h, self.W2)
     p = tf.nn.softmax(logp)
     return p
def predict_UP(self,x):
    feed = {self.tf_x: np.reshape(x, (1, -1))}
    aprob = self.session.run(self.tf_aprob, feed);
    return aprob
  1. PolicyNetwork智能体使用update方法更新权重:
def update(self, feed):
    return self.session.run(self.train_op, feed)
  1. 我们定义一个辅助函数来预处理观察状态空间:
# downsampling
def preprocess(I):
    """ prepro 210x160x3 uint8 frame into 6400 (80x80) 1D float vector """
    I = I[35:195] # crop
    I = I[::2,::2,0] # downsample by factor of 2
    I[I == 144] = 0  # erase background (background type 1)
    I[I == 109] = 0  # erase background (background type 2)
    I[I != 0] = 1    # everything else (paddles, ball) just set to 1
    return I.astype(np.float).ravel()
  1. 其余的很简单-我们创建一个游戏环境,定义要持有的数组(状态,动作,奖励,状态),并使智能体学习大量情节(休息或连续不断),这完全取决于您的计算能力和资源)。 这里要注意的重要一点是,智能体没有按动作步骤学习。 相反,智能体使用一个情节的完整(状态,动作,奖励,状态)集来纠正其策略。 这可能会占用大量内存:
if __name__ == '__main__':
    # Create Game Environment
    env_name = "Pong-v0"
    env = gym.make(env_name)
    env = wrappers.Monitor(env, '/tmp/pong', force=True)
    n_actions = env.action_space.n  # Number of possible actions
    # Initializing Game and State(t-1), action, reward, state(t)
    xs, rs, ys = [], [], []
    obs = env.reset()
    prev_x = None
    running_reward = None
    running_rewards = []
    reward_sum = 0
    n = 0
    done = False
    n_size = 80
    num_episodes = 500
    #Create Agent
    agent = PolicyNetwork(n_size)
    # training loop
    while not done and n< num_episodes:
        # Preprocess the observation
        cur_x = preprocess(obs)
        x = cur_x - prev_x if prev_x is not None else np.zeros(n_size*n_size)
        prev_x = cur_x
        #Predict the action
        aprob = agent.predict_UP(x) ; aprob = aprob[0,:]
        action = np.random.choice(n_actions, p=aprob)
        #print(action)
        label = np.zeros_like(aprob) ; label[action] = 1
        # Step the environment and get new measurements
        obs, reward, done, info = env.step(action)
        env.render()
        reward_sum += reward
        # record game history
        xs.append(x) ; ys.append(label) ; rs.append(reward)
        if done:
            # update running reward
            running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01
            running_rewards.append(running_reward)
            feed = {agent.tf_x: np.vstack(xs), agent.tf_epr: np.vstack(rs), agent.tf_y: np.vstack(ys)}
            agent.update(feed)
            # print progress console
            if n % 10 == 0:
                print ('ep {}: reward: {}, mean reward: {:3f}'.format(n, reward_sum, running_reward))
            else:
                print ('\tep {}: reward: {}'.format(n, reward_sum))
            # Start next episode and save model
            xs, rs, ys = [], [], []
            obs = env.reset()
            n += 1 # the Next Episode
            reward_sum = 0
            if n % 50 == 0:
                agent.save()
            done = False
    plt.plot(running_rewards)
    plt.xlabel('episodes')
    plt.ylabel('Running Averge')
    plt.show()
    env.close()

下图显示了智能体在前 500 个情节中学习时的平均运行奖励:

工作原理

权重使用 Xavier 初始化进行了初始化,这确保了我们的权重既不会太大也不会太小。 两种情况都阻碍了网络的学习。 在 Xavier 初始化中,为权重分配一个具有零均值和特定方差2/(nin+nout)的值,其中ninnout该层的输入和输出数。 要了解有关 Xavier 初始化的更多信息,请参阅 Glorot 和 Bengio 在 2009 年发表的论文。 有关详细信息,请参见“另见”部分。

更多

看到智能体第一次学习演奏的任何人都会对此感到惊讶-看起来很像人。 最初的举动总是很笨拙。 缓慢地,坐席会学习走哪条路,尽管速度很慢并且经常会错过球。 但是,随着学习的继续,智能体将成为专家。

但这与我们很不一样。 一旦学会玩游戏,我们便可以在其他任何类似情况下轻松使用该知识。 RL 智能体将无法执行此操作-即使是简单的事情(例如更改环境空间的大小)也会将其恢复为零。 迁移学习是研究人员正在研究的一种技术,它可以帮助主体在另一环境空间中的一个环境中使用它所学到的知识,也许有一天可以为真正的人工智能奠定基础。

AlphaGo Zero

最近,DeepMind 发表了有关 AlphaGo Zero(AlphaGo 的最新版本)的文章。 根据他们发布的结果,AlphaGo Zero 甚至更强大,并且是历史上最强大的围棋选手。 AlphaGo 从表格状态开始,即从空白状态开始,并且仅使用棋盘状态和与其对抗的游戏来调整神经网络并预测正确的动作。

AlphaGo Zero 使用深层神经网络,该网络将原始板表示形式(当前和历史)作为输入,并输出移动概率和值。 因此,该神经网络结合了策略网络和值网络的作用。 该网络是通过自玩游戏进行训练的,这与以前的 AlphaGo 版本不同(它们是使用监督学习进行训练的)。 在每个位置上,由神经网络指导执行蒙特卡洛树搜索(MCTS)。 通过使用 MCTS 播放每个动作的自演强化学习算法来训练神经网络。

最初,神经网络的权重是随机初始化的。 在每个迭代步骤中,都会生成许多自玩游戏。 在每个时间步,使用神经网络的先前迭代对可能的策略执行 MCTS 搜索,然后通过对搜索概率进行采样来进行移动。 重复此过程直到该特定游戏终止。 存储游戏状态,采取的策略以及游戏每个时间步骤的奖励。 并行地,根据自播放的先前迭代的所有时间步长之间均匀采样的数据训练神经网络。 调整神经网络的权重,以最小化预测值和自赢者之间的误差,并使神经网络移动概率与搜索概率的相似性最大化。

在配备 4 个 TPU 的单台机器上仅进行了 3 天的训练,AlphaGo Zero 以 100-0 击败 AlphaGo。 AlphaGo Zero 完全基于 RL。 可以在 2017 年 10 月发表于《自然》上的论文《掌握无人掌握的围棋游戏》中阅读其实现的详细信息。

另见

十、移动计算

在本章中,我们将讨论在移动设备上使用深度学习的问题,并为以下内容提供一些方法:

  • 安装适用于 macOS 和 Android 的 TensorFlow Mobile
  • 玩转 TensorFlow 和 Android 示例
  • 为 MacOS 和 iPhone 安装 TensorFlow Mobile
  • 为移动设备优化 TensorFlow 图
  • 转换移动设备的 TensorFlow 图

介绍

在本节中,我们将介绍移动深度学习的一些用例。 这与台式机或云深度学习的情况大不相同,在台式机或云深度学习中,GPU 和电力通常可用。 实际上,在移动设备上,保存电池非常重要,并且 GPU 经常不可用。 但是,深度学习在许多情况下可能非常有用。 让我们回顾一下:

  • 图像识别:现代手机具有功能强大的摄像头,用户热衷于尝试对图像和图片产生效果。 通常,了解图片中的内容也很重要,并且有多种适用于此的预训练模型,如专用于 CNN 的章节所述。 这里给出了用于图像识别的模型的一个很好的例子
  • 对象定位:识别运动对象是一项关键操作,对于视频和图像处理是必需的。 例如,可以想象如果在图像中识别出多个人,那么相机将使用多个对焦点。 这里提供了对象本地化示例的集合
  • 光学字符识别:在许多活动(例如文本分类和推荐)中,识别手写字符都是至关重要的。 深度学习可以为开展这些活动提供根本帮助。 在专用于 CNN 的章节中,我们研究了 MNIST 识别的一些示例。 关于 MNIST 的信息也可以在这个页面中找到。
  • 语音识别:语音识别是访问现代电话的常用界面。 因此,深度学习用于识别语音和口头命令。 在过去的几年中,这方面的进展令人印象深刻。
  • 翻译:处理多种语言是现代多元文化世界的一部分。 手机在各种语言之间进行即时翻译的准确率越来越高,深度学习帮助打破了障碍,而这在几年前是无法想象的。 在专门针对 RNN 的一章中,我们研究了一些机器翻译示例。
  • 手势识别:电话开始使用手势作为接收命令的界面。 当然,有一些模型。
  • 压缩:压缩是手机的关键方面。 可以想象,在通过网络发送图像或视频之前减少空间是有益的。 同样,在本地存储在设备上之前压缩数据可能会很方便。 在所有这些情况下,深度学习都可以提供帮助。 使用 RNNS 进行压缩的模型位于这里

TensorFlow,移动和云

如上所述,电话通常没有 GPU,因此节省电池电量非常重要。 为了减轻成本,需要将许多昂贵的计算卸载到云中。 当然,要折衷考虑各种因素,包括在移动设备上执行深度学习模型的成本,将数据移至云的成本,用于此传输的电池成本以及云计算的成本。 没有单一的解决方案,最佳策略取决于您的具体情况。

安装适用于 macOS 和 Android 的 TensorFlow Mobile

在本秘籍中,我们将学习如何为移动环境设置 TensorFlow。 我的环境是 macOS,我为 Android 开发。 但是,在以下秘籍中将描述其他配置。

准备

我们将使用 Android Studio,这是适用于 Google Android 操作系统的官方集成开发环境IDE)。

操作步骤

我们继续按以下步骤安装适用于 macOS 和 Android 的 TensorFlow mobile:

  1. 这里安装 Android Studio。
  2. 创建一个新的项目名称AndroidExampleTensorflow,如以下屏幕截图所示:

在 AndroidStudio 中创建 TensorFlow 移动应用的示例,第一步如下图所示:选择电话和表格选项:

在 AndroidStudio 中创建 TensorFlow 移动应用的示例,第二步并选择一个空活动,如下图所示:

在 AndroidStudio 中创建 TensorFlow 移动应用的示例,第三步然后自定义MainActivity,如下图所示:

在 AndroidStudio 中创建 TensorFlow 移动应用的示例,第四步称为“基础神经节”,根据神经科学,它负责选择动作,即帮助我们确定在任何给定时间执行几个可能动作中的哪个。

  1. 将以下行插入build.gradle应用中,如以下代码所示:
// added for automatically connect to TensorFlow via maven
repositories {
jcenter()
maven {
url 'https://google.bintray.com/TensorFlow'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
// added for automatically compile TensorFlow
compile 'org.TensorFlow:TensorFlow-android:+'
testCompile 'junit:junit:4.12'
}

以下屏幕截图显示了插入的代码:

  1. 运行项目并获得结果:

使用 AndroidStudio 进行编译的示例,其中显示了连接的设备。

在 AndroidStudio 中创建 TensorFlow 移动应用的示例。 一个简单的Hello World应用

工作原理

使用 Android Studio 设置 Android TensorFlow 非常简单。 您只需要在应用的build.gradle文件中添加一些配置行,Android Studio 就会代表您执行所有操作。

更多

如果要直接从 TensorFlow 源构建,则需要安装 Bazel 和 TensorFlow。 Bazel 是一个快速,可扩展,多语言和可扩展的构建系统。 Google 内部使用了构建工具 Blaze,并将 Blaze 工具的开源部分称为 Bazel。 名称是 Blaze 的字谜。

此页面将指导您完成该过程

如果您正在运行 macOS,则过程非常简单:

  1. 按照这个页面上的说明安装 Bazel。 对于 macOS,我们将使用 Homebrew:
/usr/bin/ruby -e "$(curl -fsSL \
 https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install bazel
bazel version
brew upgrade bazel
  1. 从 GitHub 克隆 TensorFlow 发行版。
git clone https://github.com/TensorFlow/TensorFlow.git

玩转 TensorFlow 和 Android 示例

在本秘籍中,我们将考虑 TensorFlow 发行版中提供的标准 Android 示例并将其安装在我们的移动设备上。

准备

TensorFlow 移动 Android 应用可在 GitHub 上的以下地址获得。 2017 年 10 月,该页面包含以下示例:

  • TF 分类:使用 Google Inception 模型实时对相机帧进行分类,并在相机图像上以重叠显示顶部结果。
  • TF 检测:演示使用 TensorFlow 对象检测 API 训练的 SSD-Mobilenet 模型。 这是在现代卷积目标检测器的速度/精度折衷中引入的,以实时定位和跟踪摄像机预览中的目标(来自 80 个类别)。
  • TF 风格化:使用基于艺术风格的学习表示的模型将相机预览图像重新设置为许多不同艺术风格的图像。
  • TF 语音:运行在音频训练教程中构建的简单语音识别模型。 监听一小部分单词,并在识别它们时在 UI 中突出显示它们。

操作步骤

我们按以下步骤进行:

  1. 安装包的最佳方法是使用每晚创建的预构建 APK。 将浏览器指向这里并下载TensorFlow_demo.apk,如以下屏幕截图所示:

  1. 在您的设备上安装应用。 在我的示例中,我将使用 Android Studio 中可用的 Pixel XL 仿真设备。 这是直接从 Android Studio 内部模拟的终端设备。 命令adb devices列出所有连接的设备。 在这种情况下,我有一个 Pixel XL 模拟器,可以安装TensorFlow_demo apk
adb devices
List of devices attached
emulator-5554 device
adb install -r TensorFlow_demo.apk

安装后,仿真器将具有一组新的 TensorFlow 应用可供使用,如下图所示。

  1. 运行您喜欢的应用。 例如,以下图像是 TF Stylize 的示例,用于通过 Transfer Learning 将相机预览图像重新设置为多种不同艺术风格的图像:

下图是 TF 语音的示例(请记住为仿真器激活麦克风):

工作原理

如果您使用夜间构建演示和adb工具在设备上安装 APK,则安装 Android 的 TensorFlow 示例非常容易。

为 MacOS 和 iPhone 安装 TensorFlow Mobile

在本秘籍中,我们将学习如何在移动环境中设置 TensorFlow。 我的环境是 macOS,这里的想法是为 iOS 和 iPhone 开发。

准备

我们将使用 Xcode 开发环境和 CocoaPods 来预安装 TensorFlow。 我将假定您的环境中已经安装了 Xcode。 如果没有,请从这里下载。

操作步骤

我们将按照以下步骤进行操作:

  1. 使用以下命令安装 CocoaPods
sudo gem install cocoapods
pod setup
Setting up CocoaPods master repo
$ /usr/local/git/current/bin/git clone https://github.com/CocoaPods/Specs.git master --progress
Cloning into 'master'...
remote: Counting objects: 1602077, done.
remote: Compressing objects: 100% (243/243), done.
remote: Total 1602077 (delta 125), reused 172 (delta 74), pack-reused 1601747
Receiving objects: 100% (1602077/1602077), 432.12 MiB | 1.83 MiB/s, done.
Resolving deltas: 100% (849517/849517), done.
Checking out files: 100% (188907/188907), done.
  1. 使用 CocoaPods 安装 TensorFlow 发行版:
cd TensorFlow/TensorFlow/examples/ios/benchmark
pod install
Analyzing dependencies
Downloading dependencies
Installing TensorFlow-experimental (1.1.1)
Generating Pods project
Integrating client project
[!] Please close any current Xcode sessions and use `tf_benchmark_example.xcworkspace` for this project from now on.
Sending stats
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
  1. 从 Inception v1 下载一些样本数据。 将标签和图文件提取到simplecamera文件夹内的数据文件夹中:
mkdir -p ~/graphs
 curl -o ~/graphs/inception5h.zip \
 https://storage.googleapis.com/download.TensorFlow.org/models/inception5h.zip \
 && unzip ~/graphs/inception5h.zip -d ~/graphs/inception5h
 cp ~/graphs/inception5h/* TensorFlow/examples/ios/benchmark/data/
 cp ~/graphs/inception5h/* TensorFlow/examples/ios/camera/data/
 cp ~/graphs/inception5h/* TensorFlow/examples/ios/simple/data/
  1. 从中下载用作测试的图像并将其复制到基准目录:

https://upload.wikimedia.org/wikipedia/commons/5/55/Grace_Hopper.jpg

cp grace_hopper.jpg ../../benchmark/data/


Grace Hopper 的图片

  1. 打开以前使用的示例项目。 以下命令将打开已经可用的 TensorFlow 的 Xcode 之后,运行编译,如以下代码和图像所示:
open tf_benchmark_example.xcworkspace

  1. 在 iPhone 模拟器中查看结果。 根据 Inception v1 类别,将步骤 4 中使用的图像识别为军服的图像:

用于 Tensorflow 计算的 Iphone 应用示例

TensorFlow 1.x 深度学习秘籍:6~10(3)https://developer.aliyun.com/article/1426772

相关文章
|
6天前
|
机器学习/深度学习 供应链 TensorFlow
深度学习实战营:TensorFlow+Python,打造你的数据驱动决策引擎
【9月更文挑战第13天】在数据爆炸时代,企业日益依赖精准分析进行决策。深度学习凭借其卓越的特征提取与模式识别能力,成为构建数据驱动决策引擎的关键技术。本项目通过TensorFlow和Python,利用LSTM构建零售业销量预测模型,优化库存管理和营销策略。首先确保安装TensorFlow,然后使用Keras API搭建模型,并通过训练、评估和部署流程,展示深度学习在数据驱动决策中的强大应用潜力,助力企业提升经营效率。
17 3
|
9天前
|
机器学习/深度学习 数据挖掘 TensorFlow
从数据小白到AI专家:Python数据分析与TensorFlow/PyTorch深度学习的蜕变之路
【9月更文挑战第10天】从数据新手成长为AI专家,需先掌握Python基础语法,并学会使用NumPy和Pandas进行数据分析。接着,通过Matplotlib和Seaborn实现数据可视化,最后利用TensorFlow或PyTorch探索深度学习。这一过程涉及从数据清洗、可视化到构建神经网络的多个步骤,每一步都需不断实践与学习。借助Python的强大功能及各类库的支持,你能逐步解锁数据的深层价值。
22 0
|
19天前
|
持续交付 测试技术 jenkins
JSF 邂逅持续集成,紧跟技术热点潮流,开启高效开发之旅,引发开发者强烈情感共鸣
【8月更文挑战第31天】在快速发展的软件开发领域,JavaServer Faces(JSF)这一强大的Java Web应用框架与持续集成(CI)结合,可显著提升开发效率及软件质量。持续集成通过频繁的代码集成及自动化构建测试,实现快速反馈、高质量代码、加强团队协作及简化部署流程。以Jenkins为例,配合Maven或Gradle,可轻松搭建JSF项目的CI环境,通过JUnit和Selenium编写自动化测试,确保每次构建的稳定性和正确性。
42 0
|
19天前
|
测试技术 数据库
探索JSF单元测试秘籍!如何让您的应用更稳固、更高效?揭秘成功背后的测试之道!
【8月更文挑战第31天】在 JavaServer Faces(JSF)应用开发中,确保代码质量和可维护性至关重要。本文详细介绍了如何通过单元测试实现这一目标。首先,阐述了单元测试的重要性及其对应用稳定性的影响;其次,提出了提高 JSF 应用可测试性的设计建议,如避免直接访问外部资源和使用依赖注入;最后,通过一个具体的 `UserBean` 示例,展示了如何利用 JUnit 和 Mockito 框架编写有效的单元测试。通过这些方法,不仅能够确保代码质量,还能提高开发效率和降低维护成本。
33 0
|
19天前
|
UED 开发者
哇塞!Uno Platform 数据绑定超全技巧大揭秘!从基础绑定到高级转换,优化性能让你的开发如虎添翼
【8月更文挑战第31天】在开发过程中,数据绑定是连接数据模型与用户界面的关键环节,可实现数据自动更新。Uno Platform 提供了简洁高效的数据绑定方式,使属性变化时 UI 自动同步更新。通过示例展示了基本绑定方法及使用 `Converter` 转换数据的高级技巧,如将年龄转换为格式化字符串。此外,还可利用 `BindingMode.OneTime` 提升性能。掌握这些技巧能显著提高开发效率并优化用户体验。
38 0
|
19天前
|
Apache 开发者 Java
Apache Wicket揭秘:如何巧妙利用模型与表单机制,实现Web应用高效开发?
【8月更文挑战第31天】本文深入探讨了Apache Wicket的模型与表单处理机制。Wicket作为一个组件化的Java Web框架,提供了多种模型实现,如CompoundPropertyModel等,充当组件与数据间的桥梁。文章通过示例介绍了模型创建及使用方法,并详细讲解了表单组件、提交处理及验证机制,帮助开发者更好地理解如何利用Wicket构建高效、易维护的Web应用程序。
14 0
|
19天前
|
机器学习/深度学习 人工智能 TensorFlow
深度学习入门:使用Python和TensorFlow构建你的第一个神经网络
【8月更文挑战第31天】 本文是一篇面向初学者的深度学习指南,旨在通过简洁明了的语言引导读者了解并实现他们的第一个神经网络。我们将一起探索深度学习的基本概念,并逐步构建一个能够识别手写数字的简单模型。文章将展示如何使用Python语言和TensorFlow框架来训练我们的网络,并通过直观的例子使抽象的概念具体化。无论你是编程新手还是深度学习领域的新兵,这篇文章都将成为你探索这个激动人心领域的垫脚石。
|
19天前
|
机器学习/深度学习 API TensorFlow
深入解析TensorFlow 2.x中的Keras API:快速搭建深度学习模型的实战指南
【8月更文挑战第31天】本文通过搭建手写数字识别模型的实例,详细介绍了如何利用TensorFlow 2.x中的Keras API简化深度学习模型构建流程。从环境搭建到数据准备,再到模型训练与评估,展示了Keras API的强大功能与易用性,适合初学者快速上手。通过简单的代码,即可完成卷积神经网络的构建与训练,显著降低了深度学习的技术门槛。无论是新手还是专业人士,都能从中受益,高效实现模型开发。
11 0
|
19天前
|
机器学习/深度学习 PyTorch TensorFlow
深度学习框架之争:全面解析TensorFlow与PyTorch在功能、易用性和适用场景上的比较,帮助你选择最适合项目的框架
【8月更文挑战第31天】在深度学习领域,选择合适的框架至关重要。本文通过开发图像识别系统的案例,对比了TensorFlow和PyTorch两大主流框架。TensorFlow由Google开发,功能强大,支持多种设备,适合大型项目和工业部署;PyTorch则由Facebook推出,强调灵活性和速度,尤其适用于研究和快速原型开发。通过具体示例代码展示各自特点,并分析其适用场景,帮助读者根据项目需求和个人偏好做出明智选择。
28 0
|
3天前
|
机器学习/深度学习 监控 自动驾驶
基于深度学习的图像识别技术及其应用
【9月更文挑战第16天】本文深入探讨了基于深度学习的图像识别技术,并详细阐述了其在不同领域的应用。通过分析深度学习在图像识别中的作用机制和关键技术,本文揭示了该技术在自动驾驶、医疗诊断、安防监控等领域的应用前景。同时,文章还讨论了当前面临的挑战和未来的发展方向,为读者提供了对深度学习图像识别技术的全面认识。