前言
上篇文章《使用机器学习对图片进行分类》对服装图片进行分类,本篇文章开始对文字进行分类,判断一条评论是正面评论还是负面评论。
语义分析
这篇文章将训练一个语义分析模型,它用来区分一条电影评论是正面的还是负面的,二分模型是一个非常重要且应用广泛的机器学习课题。使用的数据集包含50000条电影评论,其中25000条用于训练,另外25000条用于测试。
从官网上进行下载,代码可以查看github网站上wangrl2016/multimedia/tutorials/tensorflow/text_analysis.py文件
dataset = tf.keras.utils.get_file("aclImdb_v1", url, untar=True, cache_dir=temp_dir, cache_subdir='')随机查看其中一条评论
I'm a male, not given to women's movies, but this is really a well done special story.加载数据集
对于二分模型来说,需要建立train/pos/, train/neg/两个文件夹,train/pos/存放积极的评论,train/neg/存放消极的评论。
使用TensorFlow自带的工具将数据集分为三个部分:train,validation,test
raw_train_ds = tf.keras.utils.text_dataset_from_directory( train_dir, batch_size=batch_size, validation_split=0.2, subset='training', seed=seed)raw_val_ds = tf.keras.utils.text_dataset_from_directory( train_dir, batch_size=batch_size, validation_split=0.2, subset='validation', seed=seed)raw_test_ds = tf.keras.utils.text_dataset_from_directory( test_dir, batch_size=batch_size)从train数据集中拿出20%用于validation
Found 25000 files belonging to 2 classes.Using 20000 files for training.Found 25000 files belonging to 2 classes.Using 5000 files for validation.Found 25000 files belonging to 2 classes.可以通过遍历的方式查看数据集的内容
for text_batch, label_batch in raw_train_ds.take(1): for i in range(3): print("Review", text_batch.numpy()[i]) print("Label", label_batch.numpy()[i])数据清洗
使用TextVectorization层对数据进行清洗,主要包含标准化,分割,数字化三个步骤。
定义一个字符串处理函数
def custom_standardization(input_data): lowercase = tf.strings.lower(input_data) stripped_html = tf.strings.regex_replace(lowercase, '
', ' ') return tf.strings.regex_replace(stripped_html, '[%s]' % re.escape(string.punctuation), '')定义一个TextVectorization层,将字符串处理函数传递进去
max_features = 10000sequence_length = 250vectorize_layer = layers.TextVectorization( standardize=custom_standardization, max_tokens=max_features, output_mode='int', output_sequence_length=sequence_length)通过adapt方法将加载的数据集传入到TextVectorization层,只需要文本信息
# Make a text-only dataset (without labels), then call adapttrain_text = raw_train_ds.map(lambda x, y: x)vectorize_layer.adapt(train_text)将清洗后的数据利用函数打印出来,展示一个电影评论的输出
单词转化为文字
可以看到每个单词都被替换成为一个数字,通过get_vocabulary()查看每个数字对应的单词。
1287 ---> silent 313 ---> night配置缓存
在加载数据的过程中为了减少I/O操作可以将数据加载到缓存中
AUTOTUNE = tf.data.AUTOTUNEtrain_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)创建模型
model = tf.keras.Sequential([ layers.Embedding(max_features + 1, embedding_dim), layers.Dropout(0.2), layers.GlobalAveragePooling1D(), layers.Dropout(0.2), layers.Dense(1)])Embedding层:以数字化的评论作为输入,查询该层内置的数组,并向输出中增加一个维度。
GlobalAveragePooling1D层:通过平均值返回一个固定长度的数组,便于处理输入长度不相等的情况。
Dense层:内部有16个隐藏单元,连接单一输出节点。
模型
损失函数和优化器
model.compile(loss=losses.BinaryCrossentropy(from_logits=True), optimizer='adam', metrics=tf.metrics.BinaryAccuracy(threshold=0.0))训练模型
epochs = 10history = model.fit( train_ds, validation_data=val_ds, epochs=epochs)评估模型
模型接近90%的正确率,通过model.fit函数返回训练过程中的历史记录,可以看到训练过程中的损失率变化,逐步降低。
训练损失
导出模型
在上面的示例中,TextVectorization是放在模型之前,其实也可以将其放在模型之中
export_model = tf.keras.Sequential([ vectorize_layer, model, layers.Activation('sigmoid')])将数据清洗层TextVectorization放在模型之前或者之中都有各自的优点,如果放在之前可以使用CPU异步处理这些数据,放在之中就可以利用GPU获取更好的性能。
推断新数据
后续就可以使用这个模型对电影评价进行分类
examples = [ "The movie was great!", "The movie was okay.", "The movie was terrible..."]通过模型的预测如下
[[0.6073785 ] [0.42903066] [0.34582636]] | 留言与评论(共有 0 条评论) “” |