• 『TensotFlow』RNN中文文本_上


    中文文字预处理流程

    • 文本处理
      • 读取+去除特殊符号
      • 按照字段长度排序
    • 辅助数据结构生成
      • 生成 {字符:出现次数} 字典
      • 生成按出现次数排序好的字符list
      • 生成 {字符:序号} 字典
      • 生成序号list

    文本预处理生成字典是需要去重的,一般的思路是使用set数据结构来达成,不过这里使用的是collection.Counter,可以去重还能计数

    这里的文本以全唐诗为例,一般一行为1首,目的是去掉作者,生成为“[诗主体]”的格式作为RNN输入,为了保证等长,引入字符“_”在后续处理中为长度不够的诗句补齐长度

    之后生成对应的向量格式,首先做好{字符:序号} 字典并根据它生成“[序号诗]”作为向量化输入的准备

    import numpy as np
    import tensorflow as tf
    from collections import Counter
    
    poetry_file = 'poetry.txt'
    
    poetrys = []
    with open(poetry_file, 'r', encoding='utf-8') as f:
        for line in f:
            try:
                title, content = line.strip().split(':')
                content = content.replace(' ','')         # 去空格,实际上没用到
                if '_' in content or '(' in content or '' in content or '' in content or '[' in content:
                    continue
                if len(content) < 5 or len(content) > 79:
                    continue
                content = '[' + content + ']'
                poetrys.append(content)
            except Exception as e:
                pass
    
    # 依照每个元素的长度排序
    poetrys = sorted(poetrys, key=lambda poetry: len(poetry))
    print('唐诗数量:', len(poetrys))
    
    # 统计字出现次数
    all_words = []
    for poetry in poetrys:
        all_words += [word for word in poetry]
    counter = Counter(all_words)
    print(counter.items())
    # item会把字典中的每一项变成一个2元素元组,字典变成大list
    count_pairs = sorted(counter.items(), key=lambda x:-x[1])
    # 利用zip提取,因为是原生数据结构,在切片上远不如numpy的结构灵活
    words, _ = zip(*count_pairs)
    print(words)
    
    words = words[:len(words)] + (' ',)               # 后面要用' '来补齐诗句长度
    print(words)
    # 转换为字典
    word_num_map = dict(zip(words, range(len(words))))
    # 把诗词转换为向量
    to_num = lambda word: word_num_map.get(word, len(words))
    poetry_vector = [list(map(to_num, poetry)) for poetry in poetrys]

     生成RNN的batch数据,并生成标签,在这里使用了上面提到的'_'对诗句进行补齐(原因是RNN输入长度是固定的),

    batch_size = 1
    n_chunk = len(poetry_vector) // batch_size
    x_batches = []
    y_batches = []
    for i in range(n_chunk):
        start_index = i*batch_size
        end_index = start_index + batch_size
        batches = poetry_vector[start_index:end_index]
        length = max(map(len, batches))                 # 记录下最长的诗句的长度
        xdata = np.full((batch_size, length), word_num_map[' '], np.int32)
        for row in range(batch_size):
            xdata[row,:len(batches[row])] = batches[row]
        ydata = np.copy(xdata)
        ydata[:,:-1] = xdata[:,1:]
        """
            xdata             ydata
            [6,2,4,6,9]       [2,4,6,9,9]
            [1,4,2,8,5]       [4,2,8,5,5]
            """
        x_batches.append(xdata)                         # (n_chunk, batch, length)
        y_batches.append(ydata)

    由于本篇仅仅介绍预处理,所以下面列出向量化函数,这步处理之后的batch就可以作为RNN网络的输入了,

    input_data = tf.placeholder(tf.int32, [batch_size, None])
    output_targets = tf.placeholder(tf.int32, [batch_size, None])
    
    embedding = tf.get_variable("embedding",[len(words),128])
    inputs = tf.nn.embedding_lookup(embedding,input_data)
    
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    print(sess.run(inputs,feed_dict={input_data: x_batches[0]}).shape)

    解释一下 tf.nn.embedding_lookup,在之前cs231n的作业中做过类似的实现,就是把[batch [data]]映射为[batch [data [vactor]]],所以它需要提前生成一个映射用矩阵{总的字符数*RNN输入尺寸}。

    『TensotFlow』RNN中文文本_下

  • 相关阅读:
    vim使用技巧
    排序
    2020-3-27 学习面向对象的笔记
    小圆圈第三章答案
    内置函数部分用法
    Pycharm快捷键
    小猿圈第二章答案
    Typora学习笔记
    AI的真实感
    Unity 横版2D移动跳跃问题——关于一段跳与二段跳
  • 原文地址:https://www.cnblogs.com/hellcat/p/7410027.html
Copyright © 2020-2023  润新知