TensorFlow记录(一)

记录学习TensorFlow过程中遇到知识点

1.函数 tf.contrib.keras.preprocessing.sequence.pad_sequences()

用于填充数组(列表),返回一个数组类型。函数参数:

def pad_sequences(sequences: {__iter__, __len__},
                  maxlen: Any = None,
                  dtype: str = 'int32',
                  padding: str = 'pre',
                  truncating: str = 'pre',
                  value: float = 0.) -> ndarray

传入的sequence是一个序列,maxlen是填充的最大长度,padding有两种参数pre , post,分别指定在序列之前或者最后进行填充。truncating指定当最大长度少于输入序列长度时候从前面截断还是从后面截断。最后的value指定填充所用的数字。例如:

data = [[1,2,3.4],[3,4.7,5,6]]

print(type(data))
pad_data = kr.preprocessing.sequence.pad_sequences(data, maxlen=3, dtype=np.float32, truncating='pre')
print(type(pad_data))
print(pad_data)

输出:

<class 'list'>
<class 'numpy.ndarray'>
[[1.  2.  3.4]
 [4.7 5.  6. ]]

2.函数 tf.contrib.keras.utils.to_categorical()

函数将数字转化为对应的 one-hot 编码,函数参数:

def to_categorical(y: Any,
                   num_classes: Any = None,
                   dtype: str = 'float32') -> ndarray

num_class 指定编码的长度,例如:

labels = list(range(4))
labels = kr.utils.to_categorical(labels, num_classes=len(labels))

print(labels)

输出:

[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]

3.tf.flags.DEFINE_XXX()

例如:

import tensorflow as tf

FLAGS = tf.flags.FLAGS
tf.flags.DEFINE_integer('test_int', 100, 'introduce')

print(FLAGS.test_int)

使用这个函数可以定义命令行参数,尤其是对于数据集地址,等需要改变的参数,可以直接在运行文件时候外部进行改变,而非修改源代码,使用方法例如:
在这里插入图片描述

4.tf.contrib 快速处理文本数据

使用函数tf.contrib.learn.preprocessing.VocabularyProcessor(length)可以快速创建词汇表,函数调用格式:

tf.contrib.learn.preprocessing.VocabularyProcessor (max_document_length, min_frequency=0, vocabulary=None, tokenizer_fn=None)

其中max_document_length是文档的最大长度,处理过程中文档长度大于这个数值会舍去,小於则会补0,min_frequency是词频,只有超过这个数值的词语才会收录到词汇表中,第三个暂且记下(没搞懂有什么用。。),最后一个则是分词函数
例如:

import tensorflow as tf
from tensorflow.contrib import learn
import numpy as np

# 文本数据
data = ["It is a nice day", "Today is rainy", "a b c d e f g"]
# 得到最长的文本长度
max_doc_len = max(len(x.split(" ")) for x in data)
# 将数据集中每一条数据处理为最大长度,使用0补齐
vocab_processor = learn.preprocessing.VocabularyProcessor(max_doc_len)

x = np.array(list(vocab_processor.fit_transform(data)))
print(x)

打印的结果:

[[ 1  2  3  4  5  0  0]
 [ 6  2  7  0  0  0  0]
 [ 3  8  9 10 11 12 13]]

可以看到已经将每个出现的单词进行了编号,并进行了补齐。

5.文本数据随机打乱方法

这并不是tensorflow的方法,直接使用numpy就可以很方便地完成,例如:

# 先使用 random 常生于
data = np.array([x for x in "abcde"])
print(data)
# data 也就是[ a, b, c, d, e]
# 使用 全排列函数 产生一个序列
shuffle_indices = np.random.permutation(len(data))

print(shuffle_indices)
# 注意这样写的条件事 data 必须是 ndarray 类型,如果不是,可以使用 np.array()函数转化
data = data[shuffle_indices]

print(data)

输出:

['a' 'b' 'c' 'd' 'e']
[1 2 3 0 4]
['b' 'c' 'd' 'a' 'e']

6. tf.concat() 函数-拼接数组

很多地方都会使用 tf.concat()函数来进行拼接函数的结果,比如经过一些并行计算的卷积处理之后,一般都会使用这个函数将不同卷积层的结果拼接在一起再进行后续操作,之前不太理解这个函数拼接的方式,试验了几次之后算是理解了这个函数的操作,在这里记录一下。

首先,这个函数的定义如下:

def concat(values: {__len__},
           axis: Any,
           name: str = "concat")

主要是两个参数:

  • values 一般会以列表或者数组的形式传入这个参数,表示将这个列表中的所有元素都进行拼接
  • axis 指定的是进行拼接的维度

举个例子来说:

a = np.random.randint(1, 10, (2, 3, 4))
b = np.random.randint(1, 10, (2, 3, 5))

concat_op = tf.concat([a, b], axis=2)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    res = sess.run(concat_op)
    print(res.shape)

输出的结果是:

(2, 3, 9)

可以看到,是在第三个维度(axis=2)上进行拼接,简单来说,这个函数就是相应的维度上进行简单相加即可。这里进行拼接的数组有一个非常明显的特征,就是这些数组只能在指定的要进行拼接的维度上不一样,否则是不能完成拼接的。

7.tf.contrib.layers.l2_regularizer()

这是TF提供的正则化函数,如果要使用 l1 正则,那么换成 l1 即可,使用例子如下:

weights = tf.constant([[1., -2.], [-3., 4.]])
l1_op = tf.contrib.layers.l1_regularizer(.5)(weights)
l2_op = tf.contrib.layers.l2_regularizer(.5)(weights)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(l1_op))
    print(sess.run(l2_op))

输出:

5.0
7.5

这里 L1 正则没有什么问题,每一个元素的绝对值和乘以 lambda(0.5)就是5.0 .但是注意这里计算 L2 的时候,注意在实现上会将总损失值除以2然后在乘以 lambda ,也就是:

(1 * 1 + -2 * -2 + -3 * -3 + 4 * 4)  / 2 * 0.5 = 7.5 

另外,要注意到执行上面的代码会报出 WARNING, 提示 tf.contrib mudule will not be include in TensorFlow 2.0.从提示的信息来看,应该会归并到一个叫 tensorflow_addons 的mudule中吧。

8.tf.nn.embedding_lookup()函数

简单来说,这个函数的功能就是,传入一个a数组和一个索引数组,然后按照索引数组从a数组中取出相应的列组成一个新的数组返回。
这个函数的定义:

def embedding_lookup(params: Any,
                     ids: Any,
                     partition_strategy: str = "mod",
                     name: Any = None,
                     validate_indices: bool = True,
                     max_norm: Any = None) -> Union[{dtype}, Tensor, {values}, IndexedSlices, object]

主要的参数也就是 params 和 ids ,其中 params 是完整数组, ids 表示索引数组。这个函数一般用在word2vec等相关的任务中,例如传入的训练数据是一个 batch_size 的索引数组,现在要根据这个索引从完整的词汇embeddings表中拿出这些训练词向量,就可以使用这个函数。例如:

import numpy as np
import tensorflow as tf

a = tf.random_uniform(shape=[5,2])
b = tf.constant([3,4])

get_op = tf.nn.embedding_lookup(a, b)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    ta, tb, tc = sess.run([a, b, get_op])
    print(ta)
    print(tb)
    print(tc)

具体来说,比如我们对句子进行分类,往往传入的batch数据尺寸为 [batch_size, sentence_length],这个数组就是 idx 索引数组,其中 sentence_length 就是某个句子的长度(有多少单词),然后会按照这个单词的序号去 完整的词向量表中找到这个单词的词向量,这样操作的结果就是 [batch_size, sentence_length, embedding_dims]。
另外,注意上面的:

    ta, tb, tc = sess.run([a, b, get_op])

a是计算过程中随机生成的,如果想要查看这个结果,就要在一次 run 中进行获取。

9.tf.nn.softmax_cross_entropy_with_logits_v2(logits=pred, labels=Y)

这里要说明:

tf.nn.softmax_cross_entropy_with_logits_v2()

注意这个函数的两个参数,其中:
logits表示模型输出的值 也就是预测值, labels表示正确标签

logits 的输入格式是 [batch_size, n_class], labels的输入格式同上,但是要注意每一横行都要是类别的 one-hot 形式。
注意区分下面这个:

tf.nn.sparse_softmax_cross_entropy_with_logits()

传入的模型前向传播计算结果是(1, num_classes)的形式,但是labels传入的值应该是一个索引值,也就是一个类别单值,可以使用 tf.argmax(x, axis=1) 从 one-hot 编码向量中获得。

但是注意这两个函数都含有 softmax 的计算过程,因此不需要进行 softmax 进行归一化。

10.关于 one-hot 数据的生成

两种方式,一种使用 Numpy,利用单位矩阵的特点生成,例如:

n_class = 5

# 生成单条 one-hot数据
# 借助 eye 函数可以生成单位矩阵
# 后面传入数组的话, 可以表示取出第几行 根据单位矩阵的特点
# 这里生成的是 第一个值为 1 的 one-hot
res1 = np.eye(n_class)[0]
print(res1)
print('-'*30)

# 生成多条 one-hot 形式数据
index = [1,2,3]
res2 = np.eye(n_class)[index]
print(res2)

或者直接在 TF 中生成:
这个函数是tensorflow中提供的将数字标签转化为 one-hot 形式的方法:

def one_hot(indices: Any,
            depth: Any,
            on_value: Any = None,
            off_value: Any = None,
            axis: Any = None,
            dtype: Any = None,
            name: Any = None) -> Any

主要要提供的参数有 indecies 这是原始的数字标签, on_value 表示如果是正类,用什么数字表示,一般默认是1.0, off_value显然就是相反的如果是负类 ,该用什么数字进行表示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章