摘要:
合集: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
TfidfVectorizer
是 scikit-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())
解释
- 拟合数据:
vectorizer.fit_transform(documents)
会学习文本数据中的词汇表,并将每个文档转换为 TF-IDF 特征向量。 - 特征名称:
vectorizer.get_feature_names_out()
返回词汇表中的所有特征名称。 - 特征矩阵:
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_date | movie_id | user_id | is_spoiler | review_text | rating | review_summary | |
---|---|---|---|---|---|---|---|
0 | 23 September 2013 | tt1392214 | ur38303522 | True | The film Prisoners from the outside looked lik… | 10 | “Prisoners” Better than expected |
1 | 2 October 2006 | tt0095327 | ur12460427 | False | This is an animated story about a victim and h… | 10 | Great tearjerker |
2 | 2 May 2017 | tt5311514 | ur75844575 | False | I am going to keep this short but your name is… | 10 | it is amazing |
3 | 22 November 2012 | tt0017136 | ur29659325 | False | I would have given this movie more stars if it… | 1 | visuals riveting |
4 | 21 December 2004 | tt0119094 | ur0263096 | False | I mean come on. I thought this story was great… | 8 | Calm 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
四、获取案例套装
需要登录后才允许下载文件包。登录