此部分依据tensorflow教程编写
tensorflow教程中关于IMDB 数据集介绍–包含来自互联网电影数据库的 50000 条影评文本。将这些影评拆分为训练集(25000 条影评)和测试集(25000 条影评)。训练集和测试集之间达成了平衡,意味着它们包含相同数量的正面和负面影评。
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重新转换为文本
word_index = imdb.get_word_index()
word_index = {k:(v+3) for k,v in word_index.items()}
word_index["" ] = 0
word_index["" ] = 1
word_index["" ] = 2 # unknown
word_index["" ] = 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["" ],
padding='post',
maxlen=256)
test_data = keras.preprocessing.sequence.pad_sequences(test_data,
value=word_index["" ],
padding='post',
maxlen=256)
其中value参数代表起始单词,padding=‘post’代表输入和输出的维度不同,maxlen为最大维度。
此部分依据https://github.com/gaussic/text-classification-cnn-rnn 项目编写
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为同一长度
words = ['' ] + 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方法中的代码是为了测试这些方法用的,数据集读取路径需要替换成自己电脑上存储的数据集路径。