精华内容
下载资源
问答
  • 如果pip命令安装不成功,那就使用源码安装,下载源码:https://github.com/librosa/librosa/releases/, windows的可以下载zip压缩包,方便解压。 pip install pytest-runner tar xzf librosa-<版本号>.tar.gz...
  • Tensorflow系统中的优化函数主要根据传入的损失函数的梯度计算出损失函数的极值,在计算过程中会根据传入的学习率不断的修改模型中的参数,从而使神经模型在训练数据上的损失函数尽可能小,从而得到一个质量比较好的...

    Tensorflow系统中的优化函数主要根据传入的损失函数的梯度计算出损失函数的极值,在计算过程中会根据传入的学习率不断的修改模型中的参数,从而使神经模型在训练数据上的损失函数尽可能小,从而得到一个质量比较好的模型。

    Tensorflow中实现了很多的优化函数:GradientDescentOptimizer  AdagradDAOptimizer AdamOptimizer  AdagradOptimizer 等,该文档主要介绍adamoptimizer优化函数,通过该接口了解优化函数的实现和工作机制。

    在tensorflow中实现了很多种梯度优化的方法,包括自适应梯度优化算法(adamoptimizer),随机梯度下降算法SGD和简单梯度下降算法GD。各种优化器的差别在于随着训练过程学习率的调整策略不同。

    自适应算法和sgd算法比较:在测试集上SGD算法得到的效果普遍要好于自适应算法,尽管有时候在训练集上自适应算法有时候会得到更小的loss;所以很多情况下依然会选择随机梯度下降算法来计算最终的模型。

     

    Adamoptimizer初始化:

    此函数是Adam优化算法:是一个寻找全局最优点的优化算法,引入了二次方梯度校正。Adam 算法根据损失函数对每个参数的梯度的一阶矩估计和二阶矩估计动态调整针对于每个参数的学习速率。

    参数解析:

          learning_rate:控制了权重的更新比率(如 0.001)。较大的值(如 0.3)在学习率更新前会有更快的初始学习,而较小的值(如 1.0E-5)会令训练收敛到更好的性能。

          beta1:一阶矩估计的指数衰减率,一阶矩是样本的平均值

          beta2:二阶矩估计的指数衰减率,二阶矩是样本平方的平均值

          epsilon:该参数是非常小的数,其为了防止在实现中除以零

          use_locking:如果设置为true,在更新参数时使用锁操作

          name:已经创建的adamoptimizer operation的名称

     

    AdamOptimizer继承自Optimizer类,optimizer是基本的梯度优化类,该类不经常使用,使用最多的是该类的子类,AdamOptimizer继承了父类Optimizer的minimize接口,该接口添加操作节点,用于最小化loss,该函数是简单的合并了compute_gradients()与apply_gradients()函数返回为一个优化更新后的var_list;compute_gradients()主要实现计算loss的梯度,apply_gradients()主要是把计算出的梯度应用到变量上,实现变量的更新。有的时候,为了特殊目的,比如作梯度的修改,也可以调用以上两部,并把自己的对梯度的操作放在compute_gradients 与 apply_gradients 之间。

    compute_gradients()和apply_gradients()的实现可以详细展开。

     

     

    参数解析:

    Loss:是一个tensor,在该tensor中包含了需要最小化的值

    Var_list:可以是一个list也可以是tuple元组,元素的类型是tf.variable,为了得到最小化的loss可以不断的更新该list或tuple内的变量,如果不指定默认是graph中graphKeys.TRAINABLE_VARIABLES变量收集器中的变量

    Gate_gradients:如何控制梯度的计算,可以是`GATE_NONE`, `GATE_OP`, or `GATE_GRAPH`

    Aggregation_method: 指定用于组合渐变项的方法,可用的值定义在AggregationMethod类中

    Collocate_gradients_with_ops: 如果为True,尝试将渐变与相应的op进行对齐

    Grad_loss:可选项,保存为loss计算出来的梯度

    返回值:

    返回一个元素是(gradient, variable)的list,variable是指摸个变量,gradient是该变量相对于loss的梯度;其中gradient是可以为None。

    Compute_gradients主要通过调用gradients.gradients()接口实现梯度的计算,实现的过程就是求导。

     

    参数解析:

    Grads_and_vars:该参数是compute_gradients()接口的返回值

    Global_step:可选项,该参数可以记录variable更新的次数,每更新一次该值会+1

    Name:可选项,可以指定apply_gradients()返回的operation的名字

    返回值:

    该接口返回可以应用gradients梯度的operation

    Apply_gradients主要通过调用_create_slots(), _prepare(), _apply_dense(), and _apply_sparse()

    展开全文
  • 运行代码环境:Python 3 和TensorFlow 1.2 模型介绍 整个模型共分三层: 第一层:向量查找层。目的是将输入的字符汉字转化为对应的字符向量(采用的是one-hot方法) 第二层:双向LSTM。目的是有效地自动提取输入信息...
  • TensorFlow中已经把这些常用的模型封装的很好,但是在实际工作中,我们经常需要根据需求的不同对LSTM或者GRU进行一些修改,甚至需要重新实现一种RNN模型,本篇文章主要带领读者分析了解一下TensorFlow中RNN系列模型...

    概述

    循环神经网络(RNN)用于处理序列标注等问题,在自然语言处理、语音识别等有很广泛的用途。LSTM和GRU是目前使用最广泛的两个循环神经网络的模型变种,TensorFlow中已经把这些常用的模型封装的很好,但是在实际工作中,我们经常需要根据需求的不同对LSTM或者GRU进行一些修改,甚至需要重新实现一种RNN模型,本篇文章主要带领读者分析了解一下TensorFlow中RNN系列模型的实现原理,让读者在实现自己的RNN模型时有个参考。

    基本概念

    本篇主要介绍TensorFlow中RNN系列模型的源码,下面只简单回顾一下相关模型的数学公式,具体原理还请自行查找其它资料。

    RNN

    h_{t}=\sigma (W_{f}\cdot [h_{t-1},x_{t}]+b_{f})

    LSTM

    遗忘门:f_{t}=\sigma (W_{f}\cdot [h_{t-1},x_{t}]+b_{f})

    输入门:i_{t}=\sigma (W_{i}\cdot [h_{t-1},x_{t}]+b_{i})

    输出门:o_{t}=\sigma (W_{o}\cdot [h_{t-1},x_{t}]+b_{o})

    状态层:\tilde{C}=tanh(W_{c}[h_{t-1},x_{t}]+b_{c})

                    C_{t}=f_{t}\cdot C_{t-1}+i_{t}\cdot \tilde{C_{t}}

    输出层:h_{t}=o_{t}\cdot tanh(C_{t})

    GRU

    重置门:r_{t}=\sigma (W_{r}\cdot [h_{t-1},x_{t}]+b_{r})

    更新门:z_{t}=\sigma (W_{z}\cdot [h_{t-1},x_{t}]+b_{z})

    输出层:\tilde{h}=tanh(W_{h}[r_{t}\cdot h_{t-1},x_{t}])

                   h_{t}=\(1-z_{t})\cdot h_{t-1} + z_{t}\cdot \tilde{h_{t}}

    基本流程

    在TensorFlow中,RNN相关的源码主要分为两类,一类是表示基础Cell实现逻辑的类,这些类都继承自RNNCell类,主要包括BasicRNNCell、BasicLSTMCell、GRUCell等。另外一类就是让cell在不同时间轴上运转起来的循环流程控制类,包括动态单向RNN流程类tf.nn.dynamic_rnn、动态双向RNN流程类tf.nn.bidirectional_dynamic_rnn等,本篇文章主要介绍更简单一些的tf.nn.dynamic_rnn。

    RNNCells

    RNNCell

    RNNCell是所有RNN系列模型继承的基础Cell类。其原始代码如下:

    class RNNCell(base_layer.Layer):
    
      def __call__(self, inputs, state, scope=None):
        if scope is not None:
          with vs.variable_scope(scope,
                                 custom_getter=self._rnn_get_variable) as scope:
            return super(RNNCell, self).__call__(inputs, state, scope=scope)
        else:
          scope_attrname = "rnncell_scope"
          scope = getattr(self, scope_attrname, None)
          if scope is None:
            scope = vs.variable_scope(vs.get_variable_scope(),
                                      custom_getter=self._rnn_get_variable)
            setattr(self, scope_attrname, scope)
          with scope:
            return super(RNNCell, self).__call__(inputs, state)
    
      def _rnn_get_variable(self, getter, *args, **kwargs):
        variable = getter(*args, **kwargs)
        if context.in_graph_mode():
          trainable = (variable in tf_variables.trainable_variables() or
                       (isinstance(variable, tf_variables.PartitionedVariable) and
                        list(variable)[0] in tf_variables.trainable_variables()))
        else:
          trainable = variable._trainable  # pylint: disable=protected-access
        if trainable and variable not in self._trainable_weights:
          self._trainable_weights.append(variable)
        elif not trainable and variable not in self._non_trainable_weights:
          self._non_trainable_weights.append(variable)
        return variable
    
      @property
      def state_size(self):
        raise NotImplementedError("Abstract method")
    
      @property
      def output_size(self):
        raise NotImplementedError("Abstract method")
    
      def build(self, _):
        pass
    
      def zero_state(self, batch_size, dtype):
        state_size = self.state_size
        if hasattr(self, "_last_zero_state"):
          (last_state_size, last_batch_size, last_dtype,
           last_output) = getattr(self, "_last_zero_state")
          if (last_batch_size == batch_size and
              last_dtype == dtype and
              last_state_size == state_size):
            return last_output
        with ops.name_scope(type(self).__name__ + "ZeroState", values=[batch_size]):
          output = _zero_state_tensors(state_size, batch_size, dtype)
        self._last_zero_state = (state_size, batch_size, dtype, output)
        return output

    RNNCell的__call__方法的输入参数包括inputs和state,inputs是每个time_step输入的数据,是一个二维Tensor对象,两个维度分别是批次数量和每个具体的输入数据,inputs的shape为[batch_size, input_size];state是上一步Cell后保存下来的状态向量,其第一个维度也是批次数量batch_size,第二个维度根据state_size方法配置的不同,可以是状态向量(此时state的shape为[batch_size, state_size]),也可以是一个tuple,其中包含状态向量和任意自定义的其它数据(此时state的shape为[batch_size, tuple(state_size, ...)])。

    在RNNCell的__call__方法中,首先通过调用_rnn_get_variable方法把输入的variable划分为可训练参数和不可训练参数,并分别保存于该类的_trainable_weights和_nontrainable_weights成员变量中,完后调用其父类base_layer.Layer类的__call__方法,在这个方法中,最终调用的实现的Cell的call方法,所有继承自RNNCell的Cell类都需要实现一个call,这个方法的入参即是inputs和state,方法内容是每个Cell的具体计算逻辑,通过RNNCell类__call__方法的封装,使得一个Cell实例可以像一个方法一样被调用。

      def __call__(self, inputs, state, scope=None):
        if scope is not None:
          with vs.variable_scope(scope,
                                 custom_getter=self._rnn_get_variable) as scope:
            return super(RNNCell, self).__call__(inputs, state, scope=scope)
        else:
          scope_attrname = "rnncell_scope"
          scope = getattr(self, scope_attrname, None)
          if scope is None:
            scope = vs.variable_scope(vs.get_variable_scope(),
                                      custom_getter=self._rnn_get_variable)
            setattr(self, scope_attrname, scope)
          with scope:
            return super(RNNCell, self).__call__(inputs, state)
    
      def _rnn_get_variable(self, getter, *args, **kwargs):
        variable = getter(*args, **kwargs)
        if context.in_graph_mode():
          trainable = (variable in tf_variables.trainable_variables() or
                       (isinstance(variable, tf_variables.PartitionedVariable) and
                        list(variable)[0] in tf_variables.trainable_variables()))
        else:
          trainable = variable._trainable  # pylint: disable=protected-access
        if trainable and variable not in self._trainable_weights:
          self._trainable_weights.append(variable)
        elif not trainable and variable not in self._non_trainable_weights:
          self._non_trainable_weights.append(variable)
        return variable
    state_size方法和output_size方法需要相应的子Cell继承并实现,这两个方法主要用于设置状态向量state和输出向量output的维度。由于这两个方法都有@property装饰器装饰,其它类可以以属性的方式调用这两个方法。
      @property
      def state_size(self):
        raise NotImplementedError("Abstract method")
    
      @property
      def output_size(self):
        raise NotImplementedError("Abstract method")

    build方法也需要由具体的Cell继承并实现,build是base_layer.Layer类中推荐的方法,其会在__call__方法中被调用,调用前系统已经知道了当前层(Layer)输入参数的维度即类型,在build方法中用于应该调用add_variable()方法进行待学习变量的初始化工作。

      def build(self, _):
        pass

    在RNNCell中最后是zero_state方法,用于生成值为0的状态向量的值,如果具体的Cell没有设置初始化状态向量的方法,则会调用此方法生成状态向量的初始值。

      def zero_state(self, batch_size, dtype):
        state_size = self.state_size
        if hasattr(self, "_last_zero_state"):
          (last_state_size, last_batch_size, last_dtype,
           last_output) = getattr(self, "_last_zero_state")
          if (last_batch_size == batch_size and
              last_dtype == dtype and
              last_state_size == state_size):
            return last_output
        with ops.name_scope(type(self).__name__ + "ZeroState", values=[batch_size]):
          output = _zero_state_tensors(state_size, batch_size, dtype)
        self._last_zero_state = (state_size, batch_size, dtype, output)
        return output

    总结一下:

    每个具体的Cell实现应该继承自RNNCell类,同时实现__init__、build、call、state_size、output_size等方法,其中__init__、build、call三个方法是TensorFlow中实现不同功能层通用的建议流程,首先调用__init__方法保存一些配置,当获取到输入数据的维度和类型后,调用build方法初始化待学习的参数、而call方法中是真正的计算逻辑。state_size和output_size针对RNN Cell特有的两个方法,用于设置状态向量state和输出向量output的维度。

    BasicRNNCell

    rnn_cell_impl中的BasicRNNCell类实现了基础的RNN功能。

    基础的RNN只是一个需要在time_step上做多次前向传播计算的全连接网络,其隐藏层计算就是一个全连接。

    在__init__方法中,配置了状态层神经元个数num_units,使用的激活函数activation。

    在TensorFlow的不同功能层通用的建议流程,建议在__init__方法中设置base_layer.InputSpec类型的input_spec参数,用于告知输入数据的各种属性,包括输入的维度数量、每个维度的尺寸、以及数据类型等,在BasicRNNCell中设置了输入数据的维度数量为2。

      def __init__(self, num_units, activation=None, reuse=None, name=None):
        super(BasicRNNCell, self).__init__(_reuse=reuse, name=name)
        self.input_spec = base_layer.InputSpec(ndim=2)
        self._num_units = num_units
        self._activation = activation or math_ops.tanh

    BasicRNNCell的state_size方法和output_size方法把状态层神经元个数和输出层神经元个数都设置成了num_units。

      @property
      def state_size(self):
        return self._num_units
    
      @property
      def output_size(self):
        return self._num_units

    在build方法中,根据输入数据的维度,生成待学习的权重和偏置,其中传入的inputs_shape为[batch_size, input_size],input_depth即输入数据的维数,_kernel的维度为[input_depth + self._num_units, self._num_units],其中输入神经元个数即是[h_{t-1},x_{t}],输出是state_size方法的返回值即num_units。

      def build(self, inputs_shape):
        if inputs_shape[1].value is None:
          raise ValueError("Expected inputs.shape[-1] to be known, saw shape: %s"
                           % inputs_shape)
    
        input_depth = inputs_shape[1].value
        self._kernel = self.add_variable(
            _WEIGHTS_VARIABLE_NAME,
            shape=[input_depth + self._num_units, self._num_units])
        self._bias = self.add_variable(
            _BIAS_VARIABLE_NAME,
            shape=[self._num_units],
            initializer=init_ops.zeros_initializer(dtype=self.dtype))
    
        self.built = True

    call方法中,把输入参数和之前time_step的状态值整合,与_kernel相乘,加上偏置后再调用激活函数,可以看出其实就是做了一次全连接。call方法的返回值包括当前time_step的输出向量,以及当前time_step的状态向量,在普通的RNN中,当前time_step的输出向量和状态向量是一样的。

      def call(self, inputs, state):
        gate_inputs = math_ops.matmul(
            array_ops.concat([inputs, state], 1), self._kernel)
        gate_inputs = nn_ops.bias_add(gate_inputs, self._bias)
        output = self._activation(gate_inputs)
        return output, output

    BasicLSTMCell

    rnn_cell_impl中的BasicLSTMCell类实现了基础的LSTM功能。另外rnn_cell_impl中的LSTMCell则实现了更为复杂的功能,比如单元裁剪、投影层等,本篇中我们只介绍BasicLSTMCell类的实现。

    在__init__方法中,除了与BasicRNNCell一样的一些基本的配置外,BasicLSTMCell还添加了forget_bias和state_is_tuple两个配置,其中state_is_tuple如果为True,则传入call方法的state,以及call方法返回的当前time_step的state,都是以tuple格式的LSTMStateTuple类保存了当前time_step的状态层和输出层,在lstm中,这两个向量是不一样的;如果state_is_tuple为False,则call方法返回的当前time_step的state,是通过按列拼接的方式把当前time_step的状态层和输出层拼接在一个向量中返回的。

      def __init__(self, num_units, forget_bias=1.0,
                   state_is_tuple=True, activation=None, reuse=None, name=None):
        super(BasicLSTMCell, self).__init__(_reuse=reuse, name=name)
        if not state_is_tuple:
          logging.warn("%s: Using a concatenated state is slower and will soon be "
                       "deprecated.  Use state_is_tuple=True.", self)
        self.input_spec = base_layer.InputSpec(ndim=2)
        self._num_units = num_units
        self._forget_bias = forget_bias
        self._state_is_tuple = state_is_tuple
        self._activation = activation or math_ops.tanh

    正如之前讨论state_is_tuple参数的时候说到的,在state_size方法中,如果state_is_tuple为True,则state的维度为类似tuple的格式、否则为状态层和输出层拼接在一起,即2倍的num_unites。

      @property
      def state_size(self):
        return (LSTMStateTuple(self._num_units, self._num_units)
                if self._state_is_tuple else 2 * self._num_units)
    
      @property
      def output_size(self):
        return self._num_units

    build方法中,注意kernel权重的输出神经元个数为4*num_units,这里把神经元个数设置成num_units的4倍的原因,是因为在lstm的公式中,遗忘门、输入门、输出门及状态层的计算基数都是[h_{t-1},x_{t}]我们可以把这四个计算放到一起(W_{fioc}\cdot [h_{t-1},x_{t}]+b_{fioc}),在计算完以后再拆开即可。

      def build(self, inputs_shape):
        if inputs_shape[1].value is None:
          raise ValueError("Expected inputs.shape[-1] to be known, saw shape: %s"
                           % inputs_shape)
    
        input_depth = inputs_shape[1].value
        h_depth = self._num_units
        self._kernel = self.add_variable(
            _WEIGHTS_VARIABLE_NAME,
            shape=[input_depth + h_depth, 4 * self._num_units])
        self._bias = self.add_variable(
            _BIAS_VARIABLE_NAME,
            shape=[4 * self._num_units],
            initializer=init_ops.zeros_initializer(dtype=self.dtype))
    
        self.built = True

    最后看一下BasicLSTMCell类的call方法,gate_inputs即使把四个通用计算整合在一起进行计算,完后通过array_ops.split把计算结果分拆成输入门、状态层、遗忘门及输出门,完后根据公式生成新的状态向量及输出向量,根据state_is_tuple参数的值决定是把这两个向量封装进LSTMStateTuple返回,还是拼接在一起返回。

      def call(self, inputs, state):
        sigmoid = math_ops.sigmoid
        one = constant_op.constant(1, dtype=dtypes.int32)
        # Parameters of gates are concatenated into one multiply for efficiency.
        if self._state_is_tuple:
          c, h = state
        else:
          c, h = array_ops.split(value=state, num_or_size_splits=2, axis=one)
    
        gate_inputs = math_ops.matmul(
            array_ops.concat([inputs, h], 1), self._kernel)
        gate_inputs = nn_ops.bias_add(gate_inputs, self._bias)
    
        # i = input_gate, j = new_input, f = forget_gate, o = output_gate
        i, j, f, o = array_ops.split(
            value=gate_inputs, num_or_size_splits=4, axis=one)
    
        forget_bias_tensor = constant_op.constant(self._forget_bias, dtype=f.dtype)
        # Note that using `add` and `multiply` instead of `+` and `*` gives a
        # performance improvement. So using those at the cost of readability.
        add = math_ops.add
        multiply = math_ops.multiply
        new_c = add(multiply(c, sigmoid(add(f, forget_bias_tensor))),
                    multiply(sigmoid(i), self._activation(j)))
        new_h = multiply(self._activation(new_c), sigmoid(o))
    
        if self._state_is_tuple:
          new_state = LSTMStateTuple(new_c, new_h)
        else:
          new_state = array_ops.concat([new_c, new_h], 1)
        return new_h, new_state

    GRUCell

    GRUCell的__init__方法与之前的Cell类似,唯一的不同是用户可以在此设置权重初始化器及偏置初始化器。

      def __init__(self,
                   num_units,
                   activation=None,
                   reuse=None,
                   kernel_initializer=None,
                   bias_initializer=None,
                   name=None):
        super(GRUCell, self).__init__(_reuse=reuse, name=name)
    
        # Inputs must be 2-dimensional.
        self.input_spec = base_layer.InputSpec(ndim=2)
    
        self._num_units = num_units
        self._activation = activation or math_ops.tanh
        self._kernel_initializer = kernel_initializer
        self._bias_initializer = bias_initializer

    GRUCell的状态向量state和输出向量output的size都是num_units。

      @property
      def state_size(self):
        return self._num_units
    
      @property
      def output_size(self):
        return self._num_units

    在GRU的公式中,重置门和更新门的基数都是[h_{t-1},x_{t}],可以合在一起计算,所以_gate_kernel输出神经元的个数是2*num_units,状态层的基数是[r_{t}\cdot h_{t-1},x_{t}],无法合在一起计算,所以需要单独初始化candidate_kernel参数。

      def build(self, inputs_shape):
        if inputs_shape[1].value is None:
          raise ValueError("Expected inputs.shape[-1] to be known, saw shape: %s"
                           % inputs_shape)
    
        input_depth = inputs_shape[1].value
        self._gate_kernel = self.add_variable(
            "gates/%s" % _WEIGHTS_VARIABLE_NAME,
            shape=[input_depth + self._num_units, 2 * self._num_units],
            initializer=self._kernel_initializer)
        self._gate_bias = self.add_variable(
            "gates/%s" % _BIAS_VARIABLE_NAME,
            shape=[2 * self._num_units],
            initializer=(
                self._bias_initializer
                if self._bias_initializer is not None
                else init_ops.constant_initializer(1.0, dtype=self.dtype)))
        self._candidate_kernel = self.add_variable(
            "candidate/%s" % _WEIGHTS_VARIABLE_NAME,
            shape=[input_depth + self._num_units, self._num_units],
            initializer=self._kernel_initializer)
        self._candidate_bias = self.add_variable(
            "candidate/%s" % _BIAS_VARIABLE_NAME,
            shape=[self._num_units],
            initializer=(
                self._bias_initializer
                if self._bias_initializer is not None
                else init_ops.zeros_initializer(dtype=self.dtype)))
    
        self.built = True

    在call方法中,首先计算重置门和更新门,完后计算状态层,最后计算输出。

      def call(self, inputs, state):
        gate_inputs = math_ops.matmul(
            array_ops.concat([inputs, state], 1), self._gate_kernel)
        gate_inputs = nn_ops.bias_add(gate_inputs, self._gate_bias)
    
        value = math_ops.sigmoid(gate_inputs)
        r, u = array_ops.split(value=value, num_or_size_splits=2, axis=1)
    
        r_state = r * state
    
        candidate = math_ops.matmul(
            array_ops.concat([inputs, r_state], 1), self._candidate_kernel)
        candidate = nn_ops.bias_add(candidate, self._candidate_bias)
    
        c = self._activation(candidate)
        new_h = u * state + (1 - u) * c
        return new_h, new_h

    流程控制

    RNN是处理序列数据的模型,上面介绍的Cell只是序列数据中每一步需要计算的内容,所以还需要一个流程控制类从输入数据的第一步开始,计算每一步的Cell,保存返回值并传递给下一步的Cell使用,并且把最终的返回值作为整个RNN模型的返回值返回。当今的RNN从计算方向上分为单向RNN和双向RNN;从层数上分为单层RNN和多层RNN,在TensorFlow中,单向RNN控制类为tf.nn.dynamic_rnn,双向RNN控制类为tf.nn.bidirectional_dynamic_rnn,多层RNN是在普通的RNNCell外面添加了一个tensorflow.contrib.rnn.MultiRNNCell类,完后根据单向还是双向还是使用dynamic_rnn或者bidirectional_dynamic_rnn。本文只介绍tf.nn.dynamic_rnn的内容,其它类还请自行参考源码。

    dynamic_rnn

    在构建RNN模型时,在创建完我们需要的RNNCell类以后,把cell和输入参数传递给tf.nn.dynamic_rnn后,就算完成了基于具体input的RNN模型的创建了,tf.nn.dynamic_rnn返回每一步的输出outputs和最后一步的状态state,如下所示:

    # create a BasicRNNCell
    rnn_cell = tf.nn.rnn_cell.BasicRNNCell(hidden_size)
     
    # 'outputs' is a tensor of shape [batch_size, max_time, cell_state_size]
     
    # defining initial state
    initial_state = rnn_cell.zero_state(batch_size, dtype=tf.float32)
     
    # 'state' is a tensor of shape [batch_size, cell_state_size]
    outputs, state = tf.nn.dynamic_rnn(rnn_cell, input_data,
                                       initial_state=initial_state,
                                       dtype=tf.float32)
    

    dynamic_rnn方法接受的参数除了cell和inputs以外,sequence_length用于标识inputs中每一个输入的真实序列长度,因为inputs其实是一批数据,准备数据时需要按照其中最长的一个输入的长度定义inputs第二维的长度,其它短些的数据需要在后面补位,如果指定了sequence_length,那么在计算每一个输入数据时,只会计算真实长度的内容,剩下的补位数据不计算。initial_state可以定义状态的初始化内容。

    def dynamic_rnn(cell, inputs, sequence_length=None, initial_state=None,
                    dtype=None, parallel_iterations=None, swap_memory=False,
                    time_major=False, scope=None):

    一般情况下用户整理好的输入数据的维度是[batch_size, time_step, input_size]的,在dynamic_rnn方法中为了方便计算,需要把数据的维度转换成[time_stet, batch_size, input_size],如下所示,_transpose_batch_time方法即负责此转换:

    flat_input = [ops.convert_to_tensor(input_) for input_ in flat_input]
    flat_input = tuple(_transpose_batch_time(input_) for input_ in flat_input)

    如果用户传递了状态state的初始化值,则把此值直接设置为state的初始化值,否则调用RNNCell父类的zero_state把state初始化为全0的值。

        if initial_state is not None:
          state = initial_state
        else:
          if not dtype:
            raise ValueError("If there is no initial_state, you must give a dtype.")
          state = cell.zero_state(batch_size, dtype)

    完后就调用_dynamic_rnn_loop方法进行下一步处理了。_dynamic_rnn_loop方法返回了每一步的输出outputs和最后一步的状态final_state。

    (outputs, final_state) = _dynamic_rnn_loop(
            cell,
            inputs,
            state,
            parallel_iterations=parallel_iterations,
            swap_memory=swap_memory,
            sequence_length=sequence_length,
            dtype=dtype)

    可以看到dynamic_rnn方法只是对传入的参数做了一些校验,把输入参数根据计算需要改变了一下维度顺序,完后设置了状态state的初始化值,同时还设置了parallel_iterations并行化度和sequence_length等参数,完后就交给_dynamic_rnn_loop方法处理了。

    _dynamic_rnn_loop

    在_dynamic_rnn_loop方法中,主要创建了output TensorArray和input TensorArray,TensorArray在TensorFlow中可以看做是具有动态size功能的Tensor数组,output和input TensorArray的size都是time_step的值,output值创建了一个空的TensorArray,具体的值会在每一步计算完成后填入TensorArray中,input TensorArray在创建完成后,直接把输入input中的值填入其中。

      # 创建TensorArray
      def _create_ta(name, element_shape, dtype):
        return tensor_array_ops.TensorArray(dtype=dtype,
                                            size=time_steps,
                                            element_shape=element_shape,
                                            tensor_array_name=base_name + name)
    
      # 生成output TensorArray和input TensorArray
      in_graph_mode = context.in_graph_mode()
      if in_graph_mode:
        output_ta = tuple(
            _create_ta(
                "output_%d" % i,
                element_shape=(tensor_shape.TensorShape([const_batch_size])
                               .concatenate(
                                   _maybe_tensor_shape_from_tensor(out_size))),
                dtype=_infer_state_dtype(dtype, state))
            for i, out_size in enumerate(flat_output_size))
        input_ta = tuple(
            _create_ta(
                "input_%d" % i,
                element_shape=flat_input_i.shape[1:],
                dtype=flat_input_i.dtype)
            for i, flat_input_i in enumerate(flat_input))
        # 把input灌入到TensorArray中
        input_ta = tuple(ta.unstack(input_)
                         for ta, input_ in zip(input_ta, flat_input))
      else:
        output_ta = tuple([0 for _ in range(time_steps.numpy())]
                          for i in range(len(flat_output_size)))
        input_ta = flat_input

    完后就调用TensorFlow中的循环方法while_loop方法,循环time_steps次,调用_time_step执行cell计算,更新time、output_ta及state的值。

      loop_bound = time_steps
      _, output_final_ta, final_state = control_flow_ops.while_loop(
          cond=lambda time, *_: time < loop_bound,
          body=_time_step,
          loop_vars=(time, output_ta, state),
          parallel_iterations=parallel_iterations,
          maximum_iterations=time_steps,
          swap_memory=swap_memory)

    _time_step

    首先从inputs中读取当前time_step的input值。

    input_t = tuple(ta.read(time) for ta in input_ta)

    定义调用cell的方法,传入当前time_step的input和上一步的state。

    call_cell = lambda: cell(input_t, state)

    如果设置了sequence_length参数,则调用_rnn_step方法根据每个输入的实际长度执行计算,否则直接调用call_cell(),即调用相应cell的call方法。

        if sequence_length is not None:
          (output, new_state) = _rnn_step(
              time=time,
              sequence_length=sequence_length,
              min_sequence_length=min_sequence_length,
              max_sequence_length=max_sequence_length,
              zero_output=zero_output,
              state=state,
              call_cell=call_cell,
              state_size=state_size,
              skip_conditionals=True)
        else:
          (output, new_state) = call_cell()

    把当前time_step的output写入output TensorArray中。

    output_ta_t = tuple(
              ta.write(time, out) for ta, out in zip(output_ta_t, output))

    注意,return的数据,需要把time加1,另外两个返回值为更新后的输出output TensorArray,以及当前time生成的状态state。

    return (time + 1, output_ta_t, new_state)

    _rnn_step

    此方法会根据设置的sequence_length,在执行计算的同时,每个输入数据sequence_length使用空值填充。

    def _rnn_step(
        time, sequence_length, min_sequence_length, max_sequence_length,
        zero_output, state, call_cell, state_size, skip_conditionals=False):
      """Calculate one step of a dynamic RNN minibatch.
    
      Returns an (output, state) pair conditioned on `sequence_length`.
      When skip_conditionals=False, the pseudocode is something like:
    
      if t >= max_sequence_length:
        return (zero_output, state)
      if t < min_sequence_length:
        return call_cell()
    
      # Selectively output zeros or output, old state or new state depending
      # on whether we've finished calculating each row.
      new_output, new_state = call_cell()
      final_output = np.vstack([
        zero_output if time >= sequence_length[r] else new_output_r
        for r, new_output_r in enumerate(new_output)
      ])
      final_state = np.vstack([
        state[r] if time >= sequence_length[r] else new_state_r
        for r, new_state_r in enumerate(new_state)
      ])
      return (final_output, final_state)
    
      Args:
        time: Python int, the current time step
        sequence_length: int32 `Tensor` vector of size [batch_size]
        min_sequence_length: int32 `Tensor` scalar, min of sequence_length
        max_sequence_length: int32 `Tensor` scalar, max of sequence_length
        zero_output: `Tensor` vector of shape [output_size]
        state: Either a single `Tensor` matrix of shape `[batch_size, state_size]`,
          or a list/tuple of such tensors.
        call_cell: lambda returning tuple of (new_output, new_state) where
          new_output is a `Tensor` matrix of shape `[batch_size, output_size]`.
          new_state is a `Tensor` matrix of shape `[batch_size, state_size]`.
        state_size: The `cell.state_size` associated with the state.
        skip_conditionals: Python bool, whether to skip using the conditional
          calculations.  This is useful for `dynamic_rnn`, where the input tensor
          matches `max_sequence_length`, and using conditionals just slows
          everything down.
    
      Returns:
        A tuple of (`final_output`, `final_state`) as given by the pseudocode above:
          final_output is a `Tensor` matrix of shape [batch_size, output_size]
          final_state is either a single `Tensor` matrix, or a tuple of such
            matrices (matching length and shapes of input `state`).
    
      Raises:
        ValueError: If the cell returns a state tuple whose length does not match
          that returned by `state_size`.
      """
    
      # Convert state to a list for ease of use
      flat_state = nest.flatten(state)
      flat_zero_output = nest.flatten(zero_output)
    
      def _copy_one_through(output, new_output):
        # TensorArray and scalar get passed through.
        if isinstance(output, tensor_array_ops.TensorArray):
          return new_output
        if output.shape.ndims == 0:
          return new_output
        # Otherwise propagate the old or the new value.
        copy_cond = (time >= sequence_length)
        with ops.colocate_with(new_output):
          return array_ops.where(copy_cond, output, new_output)
    
      def _copy_some_through(flat_new_output, flat_new_state):
        # Use broadcasting select to determine which values should get
        # the previous state & zero output, and which values should get
        # a calculated state & output.
        flat_new_output = [
            _copy_one_through(zero_output, new_output)
            for zero_output, new_output in zip(flat_zero_output, flat_new_output)]
        flat_new_state = [
            _copy_one_through(state, new_state)
            for state, new_state in zip(flat_state, flat_new_state)]
        return flat_new_output + flat_new_state
    
      def _maybe_copy_some_through():
        """Run RNN step.  Pass through either no or some past state."""
        new_output, new_state = call_cell()
    
        nest.assert_same_structure(state, new_state)
    
        flat_new_state = nest.flatten(new_state)
        flat_new_output = nest.flatten(new_output)
        return control_flow_ops.cond(
            # if t < min_seq_len: calculate and return everything
            time < min_sequence_length, lambda: flat_new_output + flat_new_state,
            # else copy some of it through
            lambda: _copy_some_through(flat_new_output, flat_new_state))
    
      # TODO(ebrevdo): skipping these conditionals may cause a slowdown,
      # but benefits from removing cond() and its gradient.  We should
      # profile with and without this switch here.
      if skip_conditionals:
        # Instead of using conditionals, perform the selective copy at all time
        # steps.  This is faster when max_seq_len is equal to the number of unrolls
        # (which is typical for dynamic_rnn).
        new_output, new_state = call_cell()
        nest.assert_same_structure(state, new_state)
        new_state = nest.flatten(new_state)
        new_output = nest.flatten(new_output)
        final_output_and_state = _copy_some_through(new_output, new_state)
      else:
        empty_update = lambda: flat_zero_output + flat_state
        final_output_and_state = control_flow_ops.cond(
            # if t >= max_seq_len: copy all state through, output zeros
            time >= max_sequence_length, empty_update,
            # otherwise calculation is required: copy some or all of it through
            _maybe_copy_some_through)
    
      if len(final_output_and_state) != len(flat_zero_output) + len(flat_state):
        raise ValueError("Internal error: state and output were not concatenated "
                         "correctly.")
      final_output = final_output_and_state[:len(flat_zero_output)]
      final_state = final_output_and_state[len(flat_zero_output):]
    
      for output, flat_output in zip(final_output, flat_zero_output):
        output.set_shape(flat_output.get_shape())
      for substate, flat_substate in zip(final_state, flat_state):
        if not isinstance(substate, tensor_array_ops.TensorArray):
          substate.set_shape(flat_substate.get_shape())
    
      final_output = nest.pack_sequence_as(
          structure=zero_output, flat_sequence=final_output)
      final_state = nest.pack_sequence_as(
          structure=state, flat_sequence=final_state)
    
      return final_output, final_state

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 需求:tensorflow加载库时不同版本依赖不同的库,加载的函数也会不一样。本文的需求是1.12.2版本,tensorflow_framework依赖的包有mkl_intel,可以调用mkl库...libtensorflow.jar:bazel编译源码后得到文件,也是修改...

    需求:tensorflow加载库时不同版本依赖不同的库,加载的函数也会不一样。本文的需求是1.12.2版本,tensorflow_framework依赖的包有mkl_intel,可以调用mkl库的函数。

    逻辑:
    tensorflow.jar:调用libtensorflow.jar和libtensorflow_jni.jar
    libtensorflow.jar:bazel编译源码后得到文件,也是修改tensorflow源码后的产物,核心需求。
    libtensorflow_jni.jar:加载so文件库。

    这里只修改了nativelibrary.java,代码改动无非是加载库以及路径。这里的路径需要了解代码,这样才知道so文件的路径,还有一个JNI_XX的变量,是最终加载库的名字,要和自己的so文件对应起来,大家也可以参考知乎的cubert的修改方式。

    不同的Linux的环境下也可能引起System.load()和System.loadlibrary()问题,大部分是环境问题,通过export添加路径到系统变量就可解决,或者再写一个专门加载so文件的so文件,原理是通过c++的函数加载so文件,将c++的代码生成一个so文件,然后利用这个so文件里的函数去加载,再或者多尝试不同版本的so文件,因为不同版本的依赖库不一样,有时候跳过报错的库也能解决问题。

    代码:java版本。

    步骤:
    1.https://github.com/tensorflow/tensorflow/blob/master/tensorflow/java/README.md 理清楚如何编译以及编译后得到的文件。踩坑记录:我是linux环境下最终只需要.jar文件,.so文件是不需要的。
    2.配置bazel环境,mys2,python,jdk,cuda,scdnn等一大堆,网上教程很多,这里需要注意的是你是cpu编译还是gpu。
    这里注意的是linux下可能需要配置path,export PATH=/home/medical/bin:$PATH,/home/medical/bin是我bazel.exe的放置位置。还需要注意的是tensorflow对应的bazel版本不一样,最好根据已知的,我这里是tensorflow1.12.2和bazel0.18,不然会很麻烦。
    3.进入tensorflow目录下编译,这里有一个坑就是cpu编译的话不需要选择Y/N,全部选择默认,否则会报错。
    还有一个就是运行./configure文件时候会让你选择路径,如果本地有多个版本的话需要注意,例如你有python2++和python3++不同版本时注意编译的版本选择,其实打开configure文件后发现一条命令就行了python3 …/tensorflow-1.12.2/configure.py $@

    4.编译完成后注意你的代码需求,java的是bazel build --config opt
    //tensorflow/java:tensorflow
    //tensorflow/java:libtensorflow_jni
    python的是bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package。搞明白自己是想要什么文件。这里生成的jar文件是没有pom.xml的。
    5.最后就是生成maven文件上传到maven库。
    自己创建一个pom文件,结合jia包,上传到服务器库:mvn deploy:deploy-file -DpomFile=pom.xml -Dfile=libtensorflow.jar -DrepositoryId=XXXX-snapshots -Durl=http://…
    上传到本地maven库:mvn install:install-file -Dfile=…jar -DgroupId=mkl.tensorflow -DartifactId=libtensorflow-SNAPSHOT-0.0.1 -Dversion=0.0.1 -Dpackaging=jar
    上传snapshot时注意pom文件里的版本号要加snapshot,而且要大写。

    结果:向量编译时速度提升一倍。

    展开全文
  • TensorFlow 2.0源码编译步骤

    千次阅读 2020-02-03 18:08:53
    TensorFlow 2.0源码编译步骤传统pip安装tensorflow限制修改bazel编译版本限制已知编译存在的问题配置configure编译选项Tips: 本文作者:Phillweston,未经允许禁止转载 传统pip安装tensorflow限制 1.AVX指令集CPU...


    本文作者:Phillweston,未经允许禁止转载

    传统pip安装tensorflow限制

    1.AVX指令集CPU使用老版本TensorFlow报错
    对于不支持AVX指令集的CPU服务器,在python中使用 import tensorflow as tf 命令时,若tensorflow版本高于1.5.0会进行如下报错。
    ubuntu:非法指令(核心转储);
    Win 10:ImportError: DLL load failed: A dynamic link library (DLL) initialization routine failed.
    2.TensorFlow版本与CUDA版本不配套
    目前最高版本的TensorFlow 2.1仅支持CUDA10.0版本,而NVIDIA最新Ubuntu驱动440.44配套的CUDA版本为10.2,无法兼容已有的TensorFlow版本。

    因此本文讨论如何通过通过源码编译的方式编译TensorFlow的Python版本和C++版本

    可选:通过conda安装tf2
    1.更换conda默认镜像源(这里以中科大源为例)

    $ conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
    $ conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
    $ conda config --set show_channel_urls yes
    

    2.conda创建tf2虚拟环境

    $ conda create -n tf2 python=3.6
    

    某版本的protobuf有bug,使用Python3.7编译TF源码可能会报错,不建议使用Python3.7版本,使用Linux系统自带的Python3版本即可
    3.进入环境

    $ source activate tf2
    

    git clone之后一定记得要–recurse-submodules递归克隆子模块(此选项目的是克隆protobuf源码部分,如果电脑中已有google protobuf也可不克隆子模块)
    需要前置安装的源码有:
    build-essential git protobuf bazel eigen
    注:
    1.bazel安装有版本限制,tensorflow-v2以上版本要求bazel版本在1.2.1以上,可以修改bazel编译版本限制
    2.TensorFlow源码编译依赖keras相关库,需要使用pip3安装keras相关模块

    $ sudo pip3 install keras
    

    3.eigen库要通过源码编译的方式安装,详情请搜索github

    修改bazel编译版本限制

    需要修改的三个文件分别是
    configure.py
    WORKSPACE
    .bazelrc
    这三个文件在源码根目录下

    1.configure.py文件修改
    修改如下两行
    _TF_MIN_BAZEL_VERSION = ‘0.29.0’
    _TF_MAX_BAZEL_VERSION = ‘0.29.1’
    最小版本要低于等于现在使用的版本
    最大版本要高于等于现在使用的版本

    2.WORKSPACE文件修改
    修改如下一行
    check_bazel_version_at_least(“0.29.0”)
    括号内的版本要低于等于现在使用的版本

    3…bazelrc文件修改
    注释掉这一行:build --enable_platform_specific_config
    如果你使用windows编译请加入这一行:build --config==linux

    前置依赖库安装完成后,我们输入./configure配置bazel编译TensorFlow编译选项

    已知编译存在的问题

    1.TensorFlow 1.x版本使用的bazel编译器版本不能高于1.0.0,建议版本低于0.29.1;而2.1及以上的版本使用的bazel编译器版本不能低于1.1.0,但使用高版本bazel编译可能报错,建议参照上述方法修改bazel编译版本限制

    2.TensorFlow 2.0及以上版本使用TensorRT 7.0版本会报错,报错提示如下所示:

    ImportError: /home/phillweston/.cache/bazel/_bazel_phillweston/116338b0ad1de73f45727b0ef63c0bc9/execroot/org_tensorflow/bazel-out/host/bin/tensorflow/python/keras/api/create_tensorflow.python_api_keras_python_api_gen.runfiles/org_tensorflow/tensorflow/compiler/tf2tensorrt/_wrap_py_utils.so: undefined symbol: _ZN15stream_executor14StreamExecutor18EnablePeerAccessToEPS0_
    Target //tensorflow/tools/pip_package:build_pip_package failed to build
    ERROR: /home/phillweston/git-repository/tensorflow/tensorflow/python/tools/BUILD:141:1 Executing genrule //tensorflow/python/keras/api:keras_python_api_gen_compat_v2 failed (Exit 1)
    

    原因未知,解决办法如下:
    1.configure的时候取消编译TensorRT
    2.使用低版本的bazel,参照 修改bazel编译版本限制这一步骤

    配置configure编译选项

    WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
    You have bazel x.xx.x installed.
    Please specify the location of python. [Default is /usr/bin/python]: 
    #检查一下这里的Python环境,建议使用Python3
    
    Found possible Python library paths:
      /opt/intel/openvino_2019.3.376/python/python3.6
      /usr/lib/python3/dist-packages
      /usr/lib/python3.6/dist-packages
      /opt/intel/openvino_2019.3.376/python/python3
      /opt/ros/melodic/lib/python2.7/dist-packages
      /usr/local/lib/python3.6/dist-packages
      /opt/intel/openvino_2019.3.376/deployment_tools/model_optimizer
      /opt/intel/openvino_2019.3.376/deployment_tools/open_model_zoo/tools/accuracy_checker
    Please input the desired Python library path to use.  Default is [/usr/lib/python3.6/dist-packages]
    /usr/local/lib/python3.6/dist-packages
    #务必检查一下这里的Python环境,确保环境与上面的python链接位置保持一致,而且要与pip install的默认安装位置一致
    
    #这个选项是询问是否开启XLA JIT编译支持。XLA(Accelerated Linear Algebra/加速线性代数)目前还是TensorFlow的实验项目,XLA 使用 JIT(Just in Time,即时编译)技术来分析用户在运行时(runtime)创建的 TensorFlow 图,专门用于实际运行时的维度和类型。作为新技术,这项编译技术还不成熟,爱折腾的“极客”读者可以选“y”,否则选择默认值“N”。
    Do you wish to build TensorFlow with XLA JIT support? [Y/n]: y
    XLA JIT support will be enabled for TensorFlow.
    
    #这个是OpenCL高级编程模型,NVIDIA GPU不支持,Intel和AMDGPU支持
    Do you wish to build TensorFlow with OpenCL SYCL support? [y/N]: n
    No OpenCL SYCL support will be enabled for TensorFlow.
    
    #这个是AMD GPU的加速库,作用类似
    #安装之前需要提前安装keras库,否则编译会报错
    Do you wish to build TensorFlow with ROCm support? [y/N]: n
    No ROCm support will be enabled for TensorFlow.
    
    #这个选项是询问是否使用CUDACUDA是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。如果用户配备有NVIDIAGPU,可以选择“y”,如果仅使用TensorFlow的CPU版本,回车确认“N”。
    Do you wish to build TensorFlow with CUDA support? [y/N]: y
    CUDA support will be enabled for TensorFlow.
    
    Do you wish to build TensorFlow with TensorRT support? [y/N]: y
    TensorRT support will be enabled for TensorFlow.
    
    Found CUDA 10.2 in:
        /usr/local/cuda/lib64
        /usr/local/cuda/include
    Found cuDNN 7 in:
        /usr/local/cuda/lib64
        /usr/local/cuda/include
    Found TensorRT 7 in:
        /usr/lib/x86_64-linux-gnu
        /usr/include/x86_64-linux-gnu
    
    #这个是设置NVIDIA显卡的计算力,建议与NVIDIA官网的数据一致
    #https://developer.nvidia.com/cuda-gpus
    Please specify a list of comma-separated CUDA compute capabilities you want to build with.
    You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus.
    Please note that each additional compute capability significantly increases your build time and binary size, and that TensorFlow only supports compute capabilities >= 3.5 [Default is: 6.1]: 
    
    
    Do you want to use clang as CUDA compiler? [y/N]: y
    Clang will be used as CUDA compiler.
    
    Do you wish to download a fresh release of clang? (Experimental) [y/N]: y
    Clang will be downloaded and used to compile tensorflow.
    
    #这个选项是指定CPU编译优化选项。默认值就是“-march=native”。这里“m”表示“machine(机器)”,“arch”就是“architecture”简写。“march”合在一起表示机器的结构,如果选择“-march=native”,则表示选择本地(native)CPU,如果本地CPU比较高级,就可以支持SSE4.2AVX等选项。这里建议选择默认值。
    Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native -Wno-sign-compare]: 
    
    #这部分是编译适用于Android NDKSDK的TensorFlow的,如果没有需求可以填N
    Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: y
    Searching for NDK and SDK installations.
    
    Please specify the home path of the Android NDK to use. [Default is /home/phillweston/Android/Sdk/ndk-bundle]:         
    
    WARNING: The NDK version in /home/phillweston/Android/Sdk/ndk-bundle is 21, which is not supported by Bazel (officially supported versions: [10, 11, 12, 13, 14, 15, 16, 17, 18]). Please use another version. Compiling Android targets may result in confusing errors.
    
    #这里如果使用高版本的NDK API限制可能导致部分低版本的API无法使用TF框架,推荐填写最低版本
    Please specify the (min) Android NDK API level to use. [Available levels: ['16', '17', '18', '19', '21', '22', '23', '24', '26', '27', '28', '29']] [Default is 21]: 16
    
    Please specify the home path of the Android SDK to use. [Default is /home/phillweston/Android/Sdk]: 
    
    Please specify the Android SDK API level to use. [Available levels: ['29']] [Default is 29]: 
    
    Please specify an Android build tools version to use. [Available versions: ['29.0.2']] [Default is 29.0.2]: 
    #Android部分到这里截止
    
    Preconfigured Bazel build configs. You can use any of the below by adding "--config=<>" to your build command. See .bazelrc for more details.
    	--config=mkl         	# Build with MKL support.
    	--config=monolithic  	# Config for mostly static monolithic build.
    	--config=ngraph      	# Build with Intel nGraph support.
    	--config=numa        	# Build with NUMA support.
    	--config=dynamic_kernels	# (Experimental) Build kernels into separate shared objects.
    	--config=v2          	# Build TensorFlow 2.x instead of 1.x.
    Preconfigured Bazel build configs to DISABLE default on features:
    	--config=noaws       	# Disable AWS S3 filesystem support.
    	--config=nogcp       	# Disable GCP support.
    	--config=nohdfs      	# Disable HDFS support.
    	--config=nonccl      	# Disable NVIDIA NCCL support.
    Configuration finished
    

    注:bazel build编译的时候,如果遇到各种问题。command会提示Use --verbose_failures to see the command lines of failed build steps.加–verbose_failures命令后bazel即可在终端显示报错信息

    命令1:编译C++版本的tensorflow

    $ bazel build --config=opt --config=cuda --config=v2 //tensorflow:libtensorflow_cc.so --verbose_failures --local_resources=8192,6,10
    

    命令2:编译python版本的tensorflow

    $ bazel build --config=opt --config=cuda --config=v2 //tensorflow/tools/pip_package:build_pip_package --verbose_failures --local_resources=8192,6,10
    

    注意:双横线不代表这里是注释,其中的双斜杠//是名字的一种起手写法,与目录表示的/完全是两个概念。

    Tips:

    从源代码编译 TensorFlow 可能会消耗大量内存。如果系统内存有限,请使用以下命令限制 bazel 的系统资源消耗量:
    1.限制内存消耗量
    –local_ram_resources=2048
    2.限制系统资源消耗量(推荐加入此编译选项,否则可能导致编译过程死机)
    –local_resources=8192,6,10是限制占用内存最多为8192 M,最多占用6个CPU,最多10个IO线程
    3.限制同时并行的最大线程数(即同时使用的最多CPU个数)
    –jobs X(线程数)

    展开全文
  • Tensorflow实例 基础 变量 TensorBoard的使用 调试 -[未完] 初级实例 跑实例时一步一步解析每一行代码,包括每个一个变量,每一个函数每一步的运行结果写在后面注释里面 ... 结束其他需要修改的大家提出来
  • GAN风格对生成器部分提出了许多更改,使其可以生成逼真的高质量图像并修改生成器部分的某些部分。 Style GAN使用基线渐进式GAN架构,并在其生成器部分中提出了一些更改。 但是,鉴别器架构与基线渐进式GAN十分相似
  • If you hate the fucking tensorflow1.x very much, no worries! I have implemented a new YOLOv3 repo with TF2.0, and also made a chinese blog on how to implement YOLOv3 object detector from scratch. ...
  • 这是一个尝试使用直接从原始C3D-caffe转换而来的模型在tensorflow上实现的存储库。 请注意,我们的Tensorflow中的实现与原始C3D Caffe之间的UCF101 split1大约有5%的视频级准确度裕度。 要求: 已安装tensorflow> ...
  • Tensorflow-101 嗨!在这里我把翻译成中文以及我自己在ipython的实作程式码记录在Jupyter Notebook里,欢迎大家取用。 查尔·RNN word2vec 执照 MIT许可证(MIT) 版权所有(c)2016 c1mone 特此免费授予获得此...
  • 本教程以读取Fashion-MNIST为例 ...本人将所有文件保存到此文档路径中:'/home/brian/Documents/tensorflow-gpu/tensorflow-learning/data/fashion/' 2 在python3环境中通过如下读入数据,并转换为numpy...
  • Tensorflow 单元测试

    2020-03-11 21:30:39
    源码编译tensorflow 源码编译tensorflow1 源码编译tensorflow2 1. 基本概念 单元测试 ...修改TensorFlow内部源码,需要使用bazel来编译,故有必要了解下bazel。bazel优点很多,主要有 构建快。支持增...
  • 源码编译TensorFlow出错和解决

    千次阅读 2017-02-28 21:46:31
    源码下载,就一直不行,经常断流,搞 了几天才下载完成。出下面的错误:并且还是修改编译文件,才算过关了。比如把文件grpc-gitclone.cmake:execute_process( COMMAND ${CMAKE_COMMAND} -E remove_directory "E:...
  • 最近使用TensorFlow object_detect API做目标检测任务,...之前写过了TensorFlow object_detect API训练自己数据的步骤以及通过修改配置文件参数降低模型输入大小和模型通道数方法达到压缩模型提高推理速率(此处)。...
  • keras里面tensorflow版ResNet101源码分析

    千次阅读 2019-08-17 17:47:08
    keras里面tensorflow版ResNet101源码分析 """ Adapted from https://gist.github.com/flyyufelix/65018873f8cb2bbe95f429c474aa1294 改编自 flyyufelix 注意:keras支持的Tensorflow----Using TensorFlow backend...
  • tensorflow1.14官方jar存在错误,请参照进行修改 特性 多线程预测,提高预测性能50% 提供模型重载,防止模型卡死 封装模型输入输出,使用更加详尽,体现性好 提供数据初步,加载char-encoder,获取文本id等特征撤除...
  • 亲自运行了Hands-On Machine Learning with Scikit-Learn and TensorFlow这本书的每个章节的源码,发现有的代码有错误,所以做了一些修改
  • 我看了网上的一些源码程序,自己下载跑一哈,发现有很多的错误,不知道是我电脑原因,还是tensorflow版本问题,我自己基于别人的源码修改了一些细节,使程序可以顺利运行 imagenet_classes.py # -*- coding: utf-...
  • 其他模型,请参考训练文件进行修改 3.资源下载 本项目详细说明,请参考鄙人博客资料: 《使用自己的数据集训练GoogLenet InceptionNet V1 V2 V3模型》: ...
  • 为了使代码正确,我不得不修改tensorflow的原始注意力机制实现。 给定一组段落,运行train.py训练模型,并运行qa_answer.py生成答案。 请通过与我联系以获取更多信息。 该代码还充当示例代码,展示了如何将...
  • Waveflow的设计使用户可以采用现有的Tensorflow模型并在Wave Computing DPU产品上进行很少或根本没有修改的情况下运行它。 waveflow将解决支持DPU的所有复杂性,从而使用户不必担心任何技术差异。 这包括在运行机器...
  • 在win10上用cmake-gui源码编译tensorflow r1.12时,configure报错: 打开tf_core_kernels.cmake,将 "${tensorflow_source_dir}/tensorflow/contrib/data/kernels/csv_dataset_op.cc" 修改为 ${tensorflow_...
  • 提交错误或者修改等反馈意见,请在Github Issues页面提交 联系邮箱(一般问题建议Github issues交流):liangqu.long AT gmail.com 高校老师索取PPT原素材等教案,请邮箱联系,并详注院校课程等信息,我们准备好了...
  • tensorflow中RNNcell源码分析以及自定义RNNCell的方法

    千次阅读 多人点赞 2017-10-31 16:44:16
    我们在仿真一些论文的时候经常会遇到一些模型,对RNN或者LSTM进行了少许的修改,或者自己定义了一种RNN的结构等情况,比如前面介绍的几篇memory networks的论文,往往都需要按照自己定义的方法来构造RNN网络。...
  • 1. 下载tensorflow源码 2. 安装依赖库 2.1 安装工具链 2.2 下载依赖文件 3. 编译文件 适用平台:linux, 嵌入式tx2, 安卓,IOS 本文以linux为例,根据自己的平台修改 1. 下载tensorflow源码 在github上下载...
  • 公司的服务器不能联网,用的cudn9.2版本,只能离线从源码安装tensorflow,查了网上的好多版本,都需要自己下载第三方库,然后修改workspace。但是这种方式改动太大,而且还有可能存在其它问题。 思考了几天之后,...
  • 这是的经过修改的存储库。 请参阅原始存储库以获取更多详细信息。 联合身体分析和姿势估计网络(JPPNet) 梁晓丹,龚科,沉和林亮,“观察人:联合的身体分析和姿势估计网络和一个新的基准”,T- 介绍 JPPNet是...

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 357
精华内容 142
关键字:

修改tensorflow源码