IMDB2019评论剧透检测竞赛和文本TF-IDF特征矩阵方案

摘要:

合集:AI案例-NLP-零售业
赛题:IMDB评论剧透检测
主办方:AI研习社
主页:https://god.yanxishe.com/20
AI问题:文本语义相似度识别
数据集:IMDB评论剧透检测数据集
数据集价值:评论剧透检测
解决方案:文本TF-IDF特征矩阵方案

一、赛题简介

赛题:IMDB评论剧透检测
主办方:AI研习社
主页:https://god.yanxishe.com/20

赛题任务

“剧透”是严重影响大家观影追剧体验的行为,本赛题就是检测剧透评论。赛题任务是:正确识别测试集影评是否为包含剧透信息,0是没有剧透,1是剧透影评。

评审标准

我们将会对比选手提交的csv文件,确认正确识别样本数量

True:模型分类正确数量 Total :测试集样本总数量

Score = 100 * (True / Total)

二、数据集内容

数据集为IMDB影评,包含电影信息,影评等信息。

1、IMDB_movie_details,包含1,572部电影信息 ,训练集train.json和测试集test.json都是影评信息,其中训练集有473,913条,测试集有100,000条。测试集、训练集正负样本比例一致。

2、关键字段说明:

movie_id : 电影ID
user_id: 用户ID
review_id: 影评ID
review_summary: 影评简介
review_text: 影评信息
is_spoiler: 是否剧透
review_data: 评论时间
rating : 评分

三、基线版解决方案

基线版解决方案原码为:执行ml.ipynb,只利用了review_text信息。优化的方向包括:

  • 文本方向:对review_summary等文字进行挖掘,以及IMDB_movie_details.json信息进行挖掘。
  • 时序方向:对review_date进行挖掘。
  • 其他方向:对movie_id,user_id,rating进行挖掘。

安装

参考《安装传统机器学习开发包》安装sklearn等开发包,还需安装以下开发包。

conda install bs4 nltk

Python中的NLTK(Natural Language Toolkit)是一个广泛使用的库,用于处理人类语言数据。它提供了丰富的工具和资源,使开发人员能够执行各种自然语言处理(NLP)任务,如文本分类、标记化、词性标注、命名实体识别、句法分析等。

BeautifulSoup 是一个用于解析 HTML 和 XML 文档的 Python 库。它提供了简单的接口来遍历、搜索和修改解析树。BeautifulSoup 通常与网页抓取(Web Scraping)任务结合使用,以便从网页中提取所需的信息。

下载停用词

import nltk
nltk.download('stopwords')

下载停用词/stopwords:

[nltk_data] Downloading package stopwords to
[nltk_data]     C:\Users\86138\AppData\Roaming\nltk_data...
[nltk_data]   Unzipping corpora\stopwords.zip.

TF-IDF特征矩阵

TF-IDF(Term Frequency-Inverse Document Frequency)是一种在信息检索和文本挖掘中常用的特征提取方法,用于评估一个词语对一份文档集或语料库中的某个文档的重要性。它结合了两部分内容:

词频(TF, Term Frequency):词频衡量的是一个词在文档中出现的频率。词频越高,表明该词在该文档中越重要。计算公式:TF(t,d)= 文档d中的总词数/词t在文档d中出现的次数。

逆文档频率(IDF, Inverse Document Frequency):逆文档频率衡量的是一个词对所有文档的区分度。如果一个词在很多文档中都出现,则它对区分文档的重要性较低;如果一个词只在少数文档中出现,它的区分度就较高。计算公式: IDF(t)=log( 包含词t的文档数 / 文档总数) 其中,log的基数通常是2或者自然对数。

TF-IDF的计算:词汇的TF-IDF值是通过将TF和IDF的值相乘得到的。这样可以同时考虑词频(该词在文档中的重要性)和逆文档频率(该词在整个文档集中的稀有性)。计算公式:TF-IDF(t,d)=TF(t,d)×IDF(t)。

举例:假设有3个文档:

  • 文档1:猫 喜欢 吃 鱼
  • 文档2:狗 喜欢 玩 玩具
  • 文档3:猫 喜欢 玩 玩具

计算TF-IDF时:

  • 对于词“猫”,它在文档1和文档3中出现,TF较高,但它在整个文档集中的IDF较低。
  • 对于词“鱼”,它只出现在文档1中,TF较高,但IDF较高,因为它在其他文档中没有出现。

总结:

  • 高TF-IDF值的词通常是能够区分不同文档的重要词汇。
  • 低TF-IDF值的词通常是常见的、在多个文档中出现的词(如“的”、“是”等)。

TF-IDF是信息检索中的一个关键概念,广泛应用于文本分类、搜索引擎排名和自然语言处理任务。

TfidfVectorizer

TfidfVectorizerscikit-learn 库中的一个类,用于将文本数据转换为 TF-IDF 特征矩阵。TF-IDF(Term Frequency-Inverse Document Frequency)是一种常用的文本特征提取方法,它结合了词频(TF)和逆文档频率(IDF)来衡量一个词在文档集中的重要性。通过 TfidfVectorizer,你可以轻松地将文本数据转换为数值特征矩阵,以便于后续的机器学习任务,如文本分类、聚类等。

以下是 TfidfVectorizer 的一些关键参数和用法:

关键参数

  • input:指定输入数据的格式,可以是 ‘filename’、’file’ 或 ‘content’。
  • encoding:指定输入文件的编码格式,默认为 ‘utf-8’。
  • decode_error:指定解码错误时的处理方式,默认为 ‘strict’。
  • strip_accents:指定是否去除文本中的重音符号,默认为 None。
  • lowercase:指定是否将文本转换为小写,默认为 True。
  • token_pattern:指定用于分割文本的正则表达式,默认为 r”(?u)\b\w\w+\b”。
  • stop_words:指定停用词列表,可以是 ‘english’、’french’ 等预定义列表,也可以自定义列表。
  • max_df:指定词频的最大阈值,默认为 1.0。
  • min_df:指定词频的最小阈值,默认为 1。
  • max_features:指定最大特征数,默认为 None。
  • ngram_range:指定 n-gram 的范围,默认为 (1, 1)。
  • use_idf:指定是否使用 IDF 权重,默认为 True。
  • smooth_idf:指定是否对 IDF 进行平滑处理,默认为 True。
  • sublinear_tf:指定是否使用亚线性 TF 权重,默认为 False。

用法示例

from sklearn.feature_extraction.text import TfidfVectorizer

# 示例文本数据
documents = [
    "This is the first document.",
    "This document is the second document.",
    "And this is the third one.",
    "Is this the first document?"
]

# 创建 TfidfVectorizer 实例
vectorizer = TfidfVectorizer()

# 拟合数据并转换为 TF-IDF 特征矩阵
tfidf_matrix = vectorizer.fit_transform(documents)

# 输出特征名称和特征矩阵
print("Feature names:", vectorizer.get_feature_names_out())
print("TF-IDF matrix:\n", tfidf_matrix.toarray())

解释

  1. 拟合数据:vectorizer.fit_transform(documents) 会学习文本数据中的词汇表,并将每个文档转换为 TF-IDF 特征向量。
  2. 特征名称:vectorizer.get_feature_names_out() 返回词汇表中的所有特征名称。
  3. 特征矩阵:tfidf_matrix.toarray() 将稀疏矩阵转换为密集矩阵,以便于查看和处理。

导入库

import re
import numpy as np
import pandas as pd
from collections import Counter
from bs4 import BeautifulSoup
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer as TF
from sklearn.naive_bayes import MultinomialNB as MNB
from sklearn.linear_model import LogisticRegression as LR
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.model_selection import cross_val_score

数据预处理

def clean_text(origin_text):
    # 去掉html标签
    text = BeautifulSoup(origin_text).get_text()
    # 去掉标点符号和非法字符
    text = re.sub("[^a-zA-Z]", " ", text)
    # 将字符全部转化为小写,并通过空格符进行分词处理
    words = text.lower().split()
    # 去停用词
    stop_words = set(stopwords.words("english"))
    meaningful_words = [w for w in words if w not in stop_words]
    # 将剩下的词还原成str类型
    cleaned_text = " ".join(meaningful_words)
    return cleaned_text

train_df = pd.read_json('./data/train.json')
test_df = pd.read_json('./data/test.json')
train_df.head()

输出:

review_datemovie_iduser_idis_spoilerreview_textratingreview_summary
023 September 2013tt1392214ur38303522TrueThe film Prisoners from the outside looked lik…10“Prisoners” Better than expected
12 October 2006tt0095327ur12460427FalseThis is an animated story about a victim and h…10Great tearjerker
22 May 2017tt5311514ur75844575FalseI am going to keep this short but your name is…10it is amazing
322 November 2012tt0017136ur29659325FalseI would have given this movie more stars if it…1visuals riveting
421 December 2004tt0119094ur0263096FalseI mean come on. I thought this story was great…8Calm Down People – Give This Picture A Break

文本转换成TF-IDF特征矩阵

train_df['text'] = train_df['review_text'].apply(lambda x: clean_text(x))
test_df['text'] = test_df['review_text'].apply(lambda x: clean_text(x))
train_df['text'].head()
# print(type(train_df['is_spoiler'][0]))
train_df['is_spoiler'] = train_df['is_spoiler'].apply(lambda x: 1 if x else 0)

train_df = train_df.sample(frac=1).reset_index(drop=True)
tfidf = TF(
    analyzer="word",
    tokenizer=None,
    preprocessor=None,
    stop_words=None,
    max_features=200)

# 数据向量化
print("Creating the tfidf vector...\n")
tfidf.fit(train_df['text'])
x_train = tfidf.transform(train_df['text'])
x_train = x_train.toarray()

x_test = tfidf.transform(test_df['text'])
x_test = x_test.toarray()

print(x_train.shape)
print(x_test.shape)
y_train = train_df['is_spoiler']
y_train.value_counts()

输出:

Creating the tfidf vector...
(473913, 200)
(100000, 200)

is_spoiler
0    349286
1    124627
Name: count, dtype: int64

输出 x_train.shape 显示训练数据的形状为 (473913, 200)。这意味着:473,913 是训练样本的数量。200 是每个样本的特征数量。

训练

使用了 scikit-learn 库中的逻辑回归(Logistic Regression)模型进行训练。输入x_train为训练数据样本,输出y_train为是否剧透。

model = LR(solver='liblinear')
model.fit(x_train, y_train)
print("10折交叉验证:")
print(np.mean(cross_val_score(model, x_train, y_train, cv=10, scoring="accuracy")))

preds = model.predict(x_test)
submission = pd.DataFrame({'id': range(len(preds)), 'pred': preds})
submission['id'] = submission['id']
submission.to_csv("./data/ml_submission.csv", index=False, header=False)
submission.head()

输出:./data/ml_submission.csv

四、获取案例套装

需要登录后才允许下载文件包。登录

发表评论