cs20si: tensorflow for research学习笔记4

在第三篇学习笔记中,我们实现了两个简单的模型,线性回归和logistic回归,对于模型结构简单的网络,我们不需要去处理他们的结构关系,但是在复杂的模型中,我们需要更好的安排模型的结构,这样方便我们debug和良好的可视化,接下来,我们就讨论一下如何结构化我们的模型。

TensorFlow中结构化模型

一般我们的模型都是由一下的两步构成,第一步是构建计算图,第二步是执行计算图,下面我们就来依次看看这两步操作中如何结构化模型。

构建计算图

在构建计算图中,一般分为下面5个步骤:

  1. 定义输入和输出的占位符(placeholder)

  2. 定义模型中需要用到的权重

  3. 定义推断模型,构建网络

  4. 定义损失函数作为优化对象

  5. 定义优化器进行优化

执行计算图

定义好了计算图之后,我们就可以构建session去进行运算,一般也分为下面5个步骤:

  1. 第一次进行运算的时候,初始化模型的所有参数

  2. 传入训练数据,可以打乱顺序

  3. 网络前向传播,计算出当前参数下的网络输出

  4. 根据网络输出和目标计算出loss

  5. 通过loss方向传播更新网络中的参数

下面是一个可视化的示意图

Paste_Image.png

实例介绍

上面是一个基本的一般性描述,下面我们使用词向量和skip-gram这个具体的例子来介绍一下如何结构化模型,如果对词向量不熟悉的同学,可以查看一下我的这篇文章的简单介绍,更加详细的介绍可以阅读这篇博文或者是cs224n的课件

词向量的简单介绍

词向量简单来说就是用一个向量去表示一个词语,但是这个向量并不是随机的,因为这样并没有任何意义,所以我们需要对每个词有一个特定的向量去表示他们,而有一些词的词性是相近的,比如"(love)喜欢"和"(like)爱",对于这种词性相近的词,我们需要他们的向量表示也能够相近,如何去度量和定义向量之间的相近呢?非常简单,就是使用两个向量的夹角,夹角越小,越相近,这样就有了一个完备的定义。

虽然我们知道了如何定义词向量的相似性,但是我们仍然不知道如何得到词向量,因为这显然不可能人为去赋值,为了得到词向量,需要介绍skip-gram模型。

skip-gram模型的简单介绍

skip-gram模型简单来讲就是在一大段话中,我们给定其中一个词语,希望预测它周围的词语,将词向量作为参数,通过这种方式来训练词向量,最后能够得到满足要求的词向量。而一般来讲,skip-gram模型都是比较简单的线性模型。另外cs224n中还介绍了Noise Contrastive Estimation(不知道怎么翻译)的方法,这里就不再详细介绍了,这只是一种负样本的取样方法。

TensorFlow实现

下面使用tensorflow的实现来具体讲解一下如何结构化模型,首先我们会实现一个非结构化版本,看看他的局限性和不足性,然后讲解一下如何结构化模型。

数据集

这里使用的是text8数据集,这是一个大约100 MB的清理过的数据集,当然这个数据集非常小并不足以训练词向量,但是我们可以得到一些有趣的结果。

构建计算图

首先定义好一些超参数。

VOCAB_SIZE = 50000
BATCH_SIZE = 128
EMBED_SIZE = 128  # dimension of the word embedding vectors
SKIP_WINDOW = 1  # the context window
NUM_SAMPLED = 64  # Number of negative examples to sample.
LEARNING_RATE = 1.0
NUM_TRAIN_STEPS = 20000
SKIP_STEP = 2000  # how many steps to skip before reporting the loss
  1. 建立输入和输出的占位符(placeholder)
    首先,我们将数据集中的所有语句按顺序排在一起,那么我们输入的是其中一个词语,比如说是第300个,那么要预测的就是他周围的词,比如第301个词,或者299个词,当然这个范围并不一定是1,一般来讲可以预测左边3个词和右边3个词中的任何一个,所以输入和输出的占位符定义如下。
center_word = tf.placeholder(tf.int32, [BATCH_SIZE], 
                             name='center_words')
y = tf.placeholder(tf.int32, [BATCH_SIZE, SKIP_WINDOW],
                   name='target_words')

这里SKIP_WINDOW表示预测周围词的数目,超参数里面取值为1。

  1. 定义词向量矩阵
    接下来需要定义词向量,使用下面的代码。
embed_matrix = tf.get_variable(
    "WordEmbedding", [VOCAB_SIZE, EMBED_SIZE],
    tf.float32,
    initializer=tf.random_uniform_initializer(-1.0, 1.0))

这里相当于新建一个Variable,维数分别是总的词数x词向量的维度。

  1. 构建网络模型
    我们可以通过下面的操作取到词向量矩阵中所需要的每一个词的词向量。
embed = tf.nn.embedding_lookup(embed_matrix, center_word, name='embed')

这里embed_matrix和center_word分别表示词向量矩阵和需要提取词向量的单词,我们都已经定义过了。

  1. 定义loss函数
    NCE已经被集成进了tensorflow,所以我们可以非常方便地进行使用,下面就是具体的api。
tf.nn.nce_loss(weights, biases, labels, inputs, num_sampled, num_classes, num_true=1, sampled_values=None, remove_accidental_hits=False, partition_strategy='mod', name='nce_loss')

labels和inputs分别是target和输入的词向量,前面有两个参数分别时weights和biases,因为词向量的维度一般不等于分类的维度,需要将词向量通过一个线性变换映射到分类下的维度。有了这个定义之后,我们就能够简单地进行实现了。

nce_weight = tf.get_variable(
            'nce_weight', [VOCAB_SIZE, EMBED_SIZE],
            initializer=tf.truncated_normal_initializer(
                stddev=1.0 / (EMBED_SIZE**0.5)))

nce_bias = tf.get_variable(
            'nce_bias', [VOCAB_SIZE], initializer=tf.zeros_initializer())

nce_loss = tf.nn.nce_loss(nce_weight, nce_bias, y, embed,
                          NUM_SAMPLED,
                          VOCAB_SIZE)
loss = tf.reduce_mean(nce_loss, 0)
  1. 定义优化函数
    接下来我们就可以定义优化函数了,非常简单,我们使用随机梯度下降法。
optimizer = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(loss)

执行计算图

构建完成计算图之后,我们就开始执行计算图了,下面就不分开讲了,直接放上整段session里面的内容。

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    total_loss = 0.0  # we use this to calculate the average loss in the last SKIP_STEP steps0
    writer = tf.summary.FileWriter('./graphs/no_frills/', sess.graph)
    for index in range(NUM_TRAIN_STEPS):
        centers, targets = next(batch_gen)
        train_dict = {center_word: centers, y: targets}
        _, loss_batch = sess.run([optimizer, loss], feed_dict=train_dict)
        total_loss += loss_batch
        if (index + 1) % SKIP_STEP == 0:
            print('Average loss at step {}: {:5.1f}'.format(
                index, total_loss / SKIP_STEP))
            total_loss = 0.0
    writer.close()

通过阅读代码,也能看到非常清晰的结构,一步一步去运行结果。

最后放上tensorboard中网络结构的示意图。

Paste_Image.png

可以发现整体的网络结构是非常混乱的,所以我们需要结构化我们的模型。

结构化网络

结构化网络非常简单,只需要加入Name Scope,下面是一个简单的事例。

with tf.name_scope(name_of_taht_scope):
    # declare op_1
    # declare op_2
    # ...

举一个例子,比如我们定义输入输出的占位符的时候,可以如下方式定义

 with tf.name_scope('data'):
    center_word = tf.placeholder(
            tf.int32, [BATCH_SIZE], name='center_words')
    y = tf.placeholder(
            tf.int32, [BATCH_SIZE, SKIP_WINDOW], name='target_words')

然后我们运行相同的代码,就能够在tensorboard里面得到下面的结果。

Paste_Image.png

是不是结构非常的清楚,所以我们平时需要结构化我们的模型,以便于更好的可视化和debug。

词向量可视化

最后在介绍一下词向量的可视化,现在tensorboraad也支持词向量的可视化了,进行一系列复杂的操作,就能够在tensorboard中得到下面的结果。

Paste_Image.png

输入每个词,都能够在右边看到与之词性相近的词语分别是什么,特别方便,这个可视化的代码在这个文件中。


本文的全部代码都在github

欢迎访问我的博客

欢迎查看我的知乎专栏,深度炼丹

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容