NLP入门-Task1 数据集探索

此部分依据tensorflow教程编写

IMDB数据集

tensorflow教程中关于IMDB 数据集介绍–包含来自互联网电影数据库的 50000 条影评文本。将这些影评拆分为训练集(25000 条影评)和测试集(25000 条影评)。训练集和测试集之间达成了平衡,意味着它们包含相同数量的正面和负面影评。

下载并处理 IMDB 数据集

TensorFlow 中包含 IMDB 数据集,已对该数据集进行了预处理,将影评(字词序列)转换为整数序列,其中每个整数表示字典中的一个特定字词。

tensorflow中使用以下代码将 IMDB 数据集下载(如果已下载该数据集,则会使用缓存副本):

imdb = keras.datasets.imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

参数 num_words=10000 保留训练数据中出现频次在前 10000 位的字词。为确保数据规模处于可管理的水平,罕见字词将被舍弃。
该数据集已经过预处理:每个样本都是一个整数数组,表示影评中的字词。每个标签都是整数值 0 或 1,其中 0 表示负面影评,1 表示正面影评。
重点看下keras中imdb.py中的load_date方法

#参数很多,都有默认值
def load_data(path='imdb.npz',
              num_words=None,
              skip_top=0,
              maxlen=None,
              seed=113,
              start_char=1,
              oov_char=2,
              index_from=3,
              **kwargs):
                
  origin_folder = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/'
  #依据get_file方法获取数据集文件
  path = get_file(
      path,
      origin=origin_folder + 'imdb.npz',
      file_hash='599dadb1135973df5b59232a0e9a887c')
  #依据imdb.npz中的四个文件得到对应的训练和测试数据集     
  with np.load(path) as f:
    x_train, labels_train = f['x_train'], f['y_train']
    x_test, labels_test = f['x_test'], f['y_test']
  
  np.random.seed(seed)
  #得到训练数据集长度的固定list
  indices = np.arange(len(x_train))
  #打乱数据顺序
  np.random.shuffle(indices)
  x_train = x_train[indices]
  labels_train = labels_train[indices]

  indices = np.arange(len(x_test))
  np.random.shuffle(indices)
  x_test = x_test[indices]
  labels_test = labels_test[indices]
  #连接训练和测试数据集
  xs = np.concatenate([x_train, x_test])
  labels = np.concatenate([labels_train, labels_test])
  
  idx = len(x_train)
  #对连接后的数据集重新分组
  x_train, y_train = np.array(xs[:idx]), np.array(labels[:idx])
  x_test, y_test = np.array(xs[idx:]), np.array(labels[idx:])

  return (x_train, y_train), (x_test, y_test)

从以上load_date方法看出,不光有获取数据集的操作,还重新对数据集进行了排序和划分。

下面代码执行显示处理后训练数据集的数据个数

print("Training entries: {}, labels: {}".format(len(train_data),len(train_labels)))
print(len(train_data[0]), len(train_data[1]))

index转成文本

下面代码是将处理后的数据集依据index重新转换为文本

word_index = imdb.get_word_index()

word_index = {k:(v+3) for k,v in word_index.items()}
word_index["<PAD>"] = 0
word_index["<START>"] = 1
word_index["<UNK>"] = 2  # unknown
word_index["<UNUSED>"] = 3

reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])

def decode_review(text):
    return ' '.join([reverse_word_index.get(i, '?') for i in text])

看下get_word_index方法

def get_word_index(path='imdb_word_index.json'):
  origin_folder = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/'
  path = get_file(
      path,
      origin=origin_folder + 'imdb_word_index.json',
      file_hash='bfafd718b763782e994055a2d397834f')
  with open(path) as f:
    return json.load(f)

主要是通过imdb_word_index.json这个词汇表文件中单词对应的index,通过上面的decode_review方法来实现index重新转换为文本。

影评(整数数组)必须转换为张量,然后才能馈送到神经网络中,通过填充数组,使它们都具有相同的长度,然后创建一个形状为 max_length * num_reviews 的整数张量。

train_data = keras.preprocessing.sequence.pad_sequences(train_data,
                                                        value=word_index["<PAD>"],
                                                        padding='post',
                                                        maxlen=256)

test_data = keras.preprocessing.sequence.pad_sequences(test_data,
                                                       value=word_index["<PAD>"],
                                                       padding='post',
                                                       maxlen=256)

其中value参数代表起始单词,padding=‘post’代表输入和输出的维度不同,maxlen为最大维度。

此部分依据https://github.com/gaussic/text-classification-cnn-rnn 项目编写

THUCNews子集探索

THUCNews子集介绍

THUCNews是清华大学自然语言处理实验室根据新浪新闻RSS订阅频道2005~2011年间的历史数据筛选过滤生成,包含74万篇新闻文档(2.19 GB),均为UTF-8纯文本格式。在原始新浪新闻分类体系的基础上,重新整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐。项目中使用的数据集是其子集,使用了其中的10个分类,每个分类6500条数据。

从原数据集生成该子集的过程参照项目helper目录中的两个脚本。其中,copy_data.sh用于从每个分类拷贝6500个文件,cnews_group.py用于将多个文件整合到一个文件中。执行该文件后,得到三个数据文件:cnews.train.txt: 训练集(50000条),cnews.val.txt: 验证集(5000条),cnews.test.txt: 测试集(10000条)

数据预处理代码

重点看下数据预处理代码cnews_loader.py:
注意该代码中有针对python2的代码,如果在python3中有可能reload(sys)找不到该方法,改为以下代码:

import importlib
importlib.reload(sys)

去掉python2的处理代码如下:

from collections import Counter
import numpy as np
import tensorflow.keras as kr

def read_file(filename):
    """读取文件数据"""
    contents, labels = [], []
    with open(filename) as f:
        for line in f:
            #异常处理
            try:
                label, content = line.strip().split('\t')
                if content:
                    contents.append(list(content))
                    labels.append(label)
            except:
                pass
    return contents, labels

def build_vocab(train_dir, vocab_dir, vocab_size=5000):
    """根据训练集构建词汇表,存储"""
    data_train, _ = read_file(train_dir)

    all_data = []
    for content in data_train:
        all_data.extend(content)

    counter = Counter(all_data)
    count_pairs = counter.most_common(vocab_size - 1)
    words, _ = list(zip(*count_pairs))
    # 添加一个 <PAD> 来将所有文本pad为同一长度
    words = ['<PAD>'] + list(words)
    open(vocab_dir, mode='w').write('\n'.join(words) + '\n')

def read_vocab(vocab_dir):
    """读取词汇表"""
    # words = open_file(vocab_dir).read().strip().split('\n')
    with open(vocab_dir) as fp:
        words = [_.strip() for _ in fp.readlines()]
    word_to_id = dict(zip(words, range(len(words))))
    return words, word_to_id

def read_category():
    """读取分类目录,固定"""
    categories = ['体育', '财经', '房产', '家居', '教育', '科技', '时尚', '时政', '游戏', '娱乐']

    categories = [x for x in categories]

    cat_to_id = dict(zip(categories, range(len(categories))))

    return categories, cat_to_id

"""将id表示的内容转换为文字,content为id矩阵"""
def to_words(content, word_to_id):
    """反转word_to_id"""
    reverse_word_index = dict([(value,key) for (key,value) in word_to_id.items()])
    return '''.join(reverse_word_index[x] for x in content)

def process_file(filename, word_to_id, cat_to_id, max_length=600):
    """将文件转换为id表示"""
    contents, labels = read_file(filename)

    data_id, label_id = [], []
    for i in range(len(contents)):
        data_id.append([word_to_id[x] for x in contents[i] if x in word_to_id])
        label_id.append(cat_to_id[labels[i]])

    # 使用keras提供的pad_sequences来将文本pad为固定长度
    x_pad = kr.preprocessing.sequence.pad_sequences(data_id, max_length)
    y_pad = kr.utils.to_categorical(label_id, num_classes=len(cat_to_id))  # 将标签转换为one-hot表示

    return x_pad, y_pad
    
def batch_iter(x, y, batch_size=64):
    """生成批次数据"""
    data_len = len(x)
    print(data_len)
    num_batch = int((data_len - 1) / batch_size) + 1
    print('num_batch',num_batch)
    #打乱数据集中的顺序
    indices = np.random.permutation(np.arange(data_len))
    x_shuffle = x[indices]
    y_shuffle = y[indices]

    for i in range(num_batch):
        start_id = i * batch_size
        end_id = min((i + 1) * batch_size, data_len)
        #yield 的函数生成迭代器
        yield x_shuffle[start_id:end_id], y_shuffle[start_id:end_id]

if __name__ == '__main__':
    contents, labels=read_file('./cnews/cnews.test.txt')
    print(contents[0])
    print(labels[0])
    #读取下载数据集中的汉字表
    words, word_to_id=read_vocab('./cnews/cnews.vocab.txt')
    print(words[0])
    print(word_to_id)
    categories, cat_to_id =read_category()
    x_pad, y_pad = process_file('./cnews/cnews.test.txt',word_to_id,cat_to_id)
    print(x_pad[0])
    print(y_pad[0])
    batch_train =batch_iter(x_pad,y_pad)
    for x_train,y_train in batch_train:
        print(x_train)
        print(y_train)

其中main方法中的代码是为了测试这些方法用的,数据集读取路径需要替换成自己电脑上存储的数据集路径。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值