文章目录
赛题背景
近年来人工智能在自然语言处理领域取得了巨大的进展。其中一项引人注目的技术是生成模型,如OpenAI的GPT-3.5。这类模型通过学习大量的文本数据,具备了生成高质量文本的能力,从而引发了一系列关于文本生成真实性的讨论。正因为生成模型的迅猛发展,也引发了一个新的挑战,即如何区分人类编写的文本与机器生成的文本。传统上,我们借助语法错误、逻辑不连贯等特征来辨别机器生成的文本,但随着生成模型的不断改进,这些特征变得越来越难以区分。因此,为了解决这一问题,研究人员开始探索使用NLP文本分类技术来区分人类编写的文本和机器生成的文本。
赛题任务
本赛题旨在构建一个文本分类模型,以区分真实对话和由ChatGPT生成的对话文本。在给定的数据集中,包含了一系列真实对话和ChatGPT生成的对话样本,参赛选手需要设计并训练一个模型,使其能够准确地将这两种类型的对话进行分类。
任务一:报名比赛,下载比赛数据集并完成读取(Pandas)
1.报名比赛
大赛官网:https://challenge.xfyun.cn/topic/info?type=text-detector&ch=vWxQGFU
2.使用Pandas库读取和加载数据集
代码如下:
import pandas as pd
train_data = pd.read_csv('./ChatGPT生成文本检测器公开数据-更新/train.csv')
test_data = pd.read_csv('./ChatGPT生成文本检测器公开数据-更新/test.csv')
print('训练集',train_data.shape)
print('测试集',test_data.shape)
# 打印训练集数据
print("训练集数据:")
print(train_data)
# 打印测试集数据
print("测试集数据:")
print(test_data)
结果如下:
训练集 (14000, 3)
测试集 (10000, 2)
练集数据:
name label content
0 1 0 [4509 3181 1253 2278 290 3562 2051 599 3125 ...
1 2 1 [ 263 1325 2563 4160 2196 169 3125 2563 2619 ...
2 3 0 [3635 177 3125 1251 3839 5212 2109 1171 1194 ...
3 4 1 [3037 266 246 3547 1253 2278 3125 649 697 ...
4 5 0 [ 177 3125 1547 4060 5212 4687 5164 3125 3974 ...
... ... ... ...
13995 13996 0 [5212 1759 1953 139 1953 3180 3187 5212 3414 ...
13996 13997 1 [ 699 778 2777 1333 224 3543 998 139 4411 ...
13997 13998 1 [ 506 211 139 3333 3293 286 4358 272 5212 ...
13998 13999 1 [1583 169 123 2969 998 5212 1759 266 1435 ...
13999 14000 0 [1759 266 4399 205 5212 1759 266 4399 205 ...
[14000 rows x 3 columns]
测试集数据:
name content
0 14001 [3125 2196 286 123 1539 1759 266 3549 649 ...
1 14002 [1109 2113 3122 213 3125 1294 5212 2338 2233 ...
2 14003 [ 236 3125 139 3037 5212 4294 1600 4550 3169 ...
3 14004 [ 13 13 13 0 0 0 245 1472 3125 ...
4 14005 [2113 2444 139 1109 4648 4626 181 3635 1145 ...
... ... ...
9995 23996 [ 430 4829 302 3447 5212 2081 2176 1146 2321 ...
9996 23997 [ 0 109 3324 532 1294 199 1370 2176 1105 ...
9997 23998 [3406 1093 5212 3036 3635 3125 3406 1296 5212 ...
9998 23999 [ 0 0 3799 248 184 5195 4399 205 434 ...
9999 24000 [2471 4553 262 1759 2579 4555 1560 4549 3125 ...
[10000 rows x 2 columns]
字段解释:
name:数据的索引或编号。
label:文本的标签,表示文本原始是否来自ChatGPT/ChatGLM。0表示人类编写的文本,1表示机器生成的文本。
content:文本经过匿名编码后的结果,按照字符进行编码。
任务二:对数据集字符进行可视化,统计标签和字符分布(Pandas)
代码如下:
# 对输入的内容进行处理
train_data['content'] = train_data['content'].apply(lambda x: x[1:-1].strip().replace('\n', ' \n '))
test_data['content'] = test_data['content'].apply(lambda x: x[1:-1].strip().replace('\n', ' \n '))
train_data['content'] = train_data['content'].apply(lambda x: x.split(' '))
test_data['content'] = test_data['content'].apply(lambda x: x.split(' '))
# 统计字符出现的频次并输出前10个最常见的字符
from collections import Counter
c = Counter()
for content in train_data['content']:
c.update(content)
c.most_common(10)
结果如下:
[('', 1242675), ('\n', 195874), ('5212', 173863), ('3125', 116815), ('1759', 72557), ('123', 69893), ('0', 61434), ('139', 58299), ('205', 43617), ('2113', 35667)]
代码如下:
# 统计字符的分布情况
train_data['content_chars'] = train_data['content'].apply(lambda x: len(''.join(x)))
test_data['content_chars'] = test_data['content'].apply(lambda x: len(''.join(x)))
train_char_distribution = train_data['content_chars'].value_counts()
test_char_distribution = test_data['content_chars'].value_counts()
print("\n训练数据字符分布:")
print(train_char_distribution)
print("\n测试数据字符分布:")
print(test_char_distribution)
结果如下:
训练数据字符分布:
740 532
738 519
742 512
739 472
743 471
...
683 1
630 1
681 1
634 1
594 1
Name: content_chars, Length: 125, dtype: int64
测试数据字符分布:
739 375
741 370
744 353
738 347
740 342
...
657 1
642 1
478 1
662 1
0 1
Name: content_chars, Length: 110, dtype: int64
代码如下:
# 统计标签的分布情况
train_label_counts = train_data['label'].value_counts()
print("训练集中标签分布情况")
print(train_label_counts)
结果如下:
训练集中标签分布情况
0 11836
1 2164
Name: label, dtype: int64
任务三:使用TFIDF提取文本特征(Sklearn)
代码如下:
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer()
tfidf.fit(train_data['content'].apply(lambda x: ' '.join(x)))
train_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
test_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
tfidf = TfidfVectorizer(ngram_range=(1,2), max_features=5000)
tfidf.fit(train_data['content'].apply(lambda x: ' '.join(x)))
train_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
test_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
结果如下:
(0, 4977) 0.06822496546597374
(0, 4970) 0.05036081773123338
(0, 4962) 0.06868770324500781
(0, 4840) 0.07855476682761314
(0, 4839) 0.049673661034006486
(0, 4723) 0.0587136638933897
(0, 4679) 0.03585397580046803
(0, 4616) 0.07963375834294922
(0, 4614) 0.05177330689441527
(0, 4523) 0.04396848344625001
(0, 4520) 0.06036582329759632
(0, 4505) 0.08710760755985235
(0, 4453) 0.07821322843323507
(0, 4343) 0.05804752886729808
(0, 4294) 0.11577465849780852
(0, 4147) 0.07812789914046314
……
任务四:使用TFIDF特征和线性模型完成训练和预测(Sklearn)
1.使用cross_val_predict()函数进行交叉验证
代码如下:
# 使用cross_val_predict()函数进行交叉验证
val_pred = cross_val_predict(
LogisticRegression(),
train_tfidf_feat,
train_data['label']
)
# 计算并输出分类报告
print(classification_report(train_data['label'], val_pred, digits=3))
结果如下:
precision recall f1-score support
0 0.985 1.000 0.992 11836
1 0.998 0.918 0.956 2164
accuracy 0.987 14000
macro avg 0.992 0.959 0.974 14000
weighted avg 0.987 0.987 0.987 14000
2.生成测试结果
代码如下:
m = LogisticRegression()
m.fit(train_tfidf_feat, train_data['label'])
test_pred = m.predict(test_tfidf_feat)
test_data['label'] = test_pred
test_data[['name', 'label']].to_csv('nlpboom.csv', index=None)
任务五:使用TFIDF特征和XGBoost完成训练和预测(Sklearn、XGBoost)
1.提取特征并使用cross_val_predict()函数进行交叉验证
代码如下:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import cross_val_predict
from xgboost import XGBClassifier
from sklearn.metrics import classification_report
tfidf = TfidfVectorizer()
tfidf.fit(train_data['content'].apply(lambda x: ' '.join(x)))
train_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
test_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=10000)
tfidf.fit(train_data['content'].apply(lambda x: ' '.join(x)))
train_tfidf_feat = tfidf.transform(train_data['content'].apply(lambda x: ' '.join(x)))
test_tfidf_feat = tfidf.transform(test_data['content'].apply(lambda x: ' '.join(x)))
val_pred = cross_val_predict(
XGBClassifier(n_estimators=50),
train_tfidf_feat,
train_data['label']
)
print(classification_report(train_data['label'], val_pred, digits=3))
结果如下:
precision recall f1-score support
0 0.992 0.997 0.994 11836
1 0.985 0.954 0.969 2164
accuracy 0.991 14000
macro avg 0.988 0.976 0.982 14000
weighted avg 0.991 0.991 0.991 14000
2.生成测试结果
代码如下:
m = XGBClassifier(n_estimators=50)
m.fit(train_tfidf_feat, train_data['label'])
test_pred = m.predict(test_tfidf_feat)
test_data['label'] = test_pred
test_data[['name', 'label']].to_csv('nloboomxgb.csv', index=None)
总结
我们可以看到使用XGBoost已经得到了不错的分数,可以在此基础上进行优化刷榜!
路漫漫其修远兮,吾将上下而求索!
愿我们都能顺心顺意!