电影评论分类:二分类问题 —— R语言实现

前言

在R和Python之间如何进行选择一直是一个热议的话题。机器学习世界也被不同语言偏好所划分。但是随着深度学习的盛行,天平逐渐向Python倾斜,因为截至目前为止Python具有大量R所没有的深度学习的资源库和框架。

但是随着Keras在R中的实现,语言选择的斗争又重新回到舞台中央。Python几乎已经慢慢变成深度学习建模的默认语言,但是随着在R中以TensorFlow(CPU和GPU均兼容)为后端的Keras框架的发行, 即便是在深度学习领域,R与Python抢占舞台的战争也再一次打响。

以下是以R语言为基础,调用Keras包的一个深度学习练习。

电影评论分类:二分类问题

1. 问题描述

二分类问题可能是应用最广泛的机器学习问题,在本例中,我们将根据电影评论的内容文字将其划分为正面或负面。

我们将使用IMDB数据集,它包含来自互联网电影数据库(IMDB) 的50000条严重两级分化的评论。数据被分为用于训练的25000条评论与用于测试的25000条评论,训练集和测试集都包含50%的正面评论和50%的负面评论。

2. 加载Keras,以及一些其他必需的库。

library(keras)
library(dplyr)
library(ggplot2)
library(purrr)

3. 下载IMDB数据集

IMDB数据集与Keras一起打包。它已经被预处理,使得评论(单词序列)已经被转换为整数序列,其中每个整数表示字典中的特定单词。

以下代码将IMDB数据集下载到您的计算机(如果您已经下载了它,则使用缓存副本):

imdb <- dataset_imdb(num_words = 10000)

c(train_data, train_labels) %<-% imdb$train
c(test_data, test_labels) %<-% imdb$test

该参数num_words = 10000保留了训练数据中最常出现的10,000个单词。丢弃罕见的单词以保持数据的大小可管理。

方便地,数据集附带一个索引映射单词到整数,必须单独下载:

word_index <- dataset_imdb_word_index()

我们已经在word_index上面下载了一个列表,其中单词为键,整数为值。如果我们从中创建数据框,我们可以方便地在两个方向上使用它。

word_index_df <- data.frame(
  word = names(word_index),
  idx = unlist(word_index, use.names = FALSE),
  stringsAsFactors = FALSE
)

# The first indices are reserved  
word_index_df <- word_index_df %>% mutate(idx = idx + 3)
word_index_df <- word_index_df %>%
  add_row(word = "<PAD>", idx = 0)%>%
  add_row(word = "<START>", idx = 1)%>%
  add_row(word = "<UNK>", idx = 2)%>%
  add_row(word = "<UNUSED>", idx = 3)

word_index_df <- word_index_df %>% arrange(idx)

4. 准备数据

train_data <- pad_sequences(
  train_data,
  value = word_index_df %>% filter(word == "<PAD>") %>% select(idx) %>% pull(),
  padding = "post",
  maxlen = 256
)

test_data <- pad_sequences(
  test_data,
  value = word_index_df %>% filter(word == "<PAD>") %>% select(idx) %>% pull(),
  padding = "post",
  maxlen = 256
)

5. 构建模型

# input shape is the vocabulary count used for the movie reviews (10,000 words)
vocab_size <- 10000

model <- keras_model_sequential()
model %>% 
  layer_embedding(input_dim = vocab_size, output_dim = 16) %>%
  layer_global_average_pooling_1d() %>%
  layer_dense(units = 16, activation = "relu") %>%
  layer_dense(units = 1, activation = "sigmoid")

model %>% summary()
损失函数和优化器
model %>% compile(
  optimizer = 'adam',
  loss = 'binary_crossentropy',
  metrics = list('accuracy')
)
创建验证集
x_val <- train_data[1:10000, ]
partial_x_train <- train_data[10001:nrow(train_data), ]

y_val <- train_labels[1:10000]
partial_y_train <- train_labels[10001:length(train_labels)]

6. 训练模型

history <- model %>% fit(
  partial_x_train,
  partial_y_train,
  epochs = 40,
  batch_size = 512,
  validation_data = list(x_val, y_val),
  verbose=1
)

在这里插入图片描述

7. 评估模型

results <- model %>% evaluate(test_data, test_labels)
results

在这里插入图片描述

小结

1)通常需要对原始数据进行大量预处理,以便将其转换为张量输入到神经网络中。单词序列可以编码为二进制向量,但也有其他编码方式。
2)带有relu激活的Dense层堆叠,可以解决很多问题(包括情感分类)。
3)对于二分类问题(两个输出类别),网络的最后一层应该是只有一个单元并使用sigmoid激活的dense层,网络输出应该是0~1范围内的标量,表示概率值。
4)对于二分类问题的sigmoid标量输出,应该使用binary_crossentropy损失函数。
5)无论问题是什么,rmsprop优化器通常都是足够好的选择。
6)随着神经网络在训练数据集上的表现越来越好,模型最终都会过拟合,并在前所未见的数据上得到越来越差的结果。一定要一直监控模型在训练集之外的数据上的性能。

参考:Tutorial: Text Classification
R语言滴水穿石系列文章(一):dplyr-高效的数据变换与整理工具
R语言绘图之ggplot2包

猜你喜欢

转载自blog.csdn.net/qq_35008279/article/details/86369931