Task03:基于机器学习的文本分类

学习目标

  • 学会文本的离散表示的原理
  • 使用sklearn的机器学习模型完成文本分类

文本表示

在自然语言领域,需要对文本进行向量表示:文本是不定长度的。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。
词嵌入是指:一个维数为所有词的数量的高维空间嵌入到一个维数低得多的连续向量空间,它是文本分类的第一步。

文本的表示方法分为离散表示和分布式表示:

  • 离散表示(离散、高维、稀疏):
    one-hot、count vector、TF-IDF、n-gram 等,
  • 分布式表示(连续、低维、稠密):
    经典模型是word2vec、Glove、ELMO、GPT、BERT。

1. One-hot:

每个字使用一个离散的向量表示。维度为字典大小,文字对应的索引处标为1,其余为0。

One-hot表示方法的例子如下:

句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海

在这里共包括11个字,因此每句话可以转换为一个11维度稀疏向量:

句子1:我 爱 北 京 天 安 门
转换为 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
句子2:我 喜 欢 上 海
转换为 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]

one-hot的问题:维度爆炸,稀疏sparse,字与字之间无关系,无法表示上下文关系等等……

2. Bag of Words:

也称count vector,使用字出现的次数来表示文本。维度是字典的大小,文字对应的索引处标为他在这条文本中出现的次数。

句子1:我 爱 北 京 天 安 门 门
句子2:我 喜 欢 上 海 我

直接统计每个字出现的次数,并进行赋值:

句子1:我 爱 北 京 天 安 门 门
转换为 [1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0]
句子2:我 喜 欢 上 海 我
转换为 [2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]

在sklearn中可以直接CountVectorizer来实现这一步骤:

from sklearn.feature_extraction.text import CountVectorizer

bag of words的问题:仅考虑了字数的出现次数,问题与onehot类似。

3. N-gram:

N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。

如果N取值为2,则句子1和句子2就变为:

句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海

操作起来也很简单:我的代码是在原文的基础上再加上bigram

train=["我 爱 北 京 天 安 门","我 喜 欢 上 海"]
train_bigram=[]
for value in train:
    lentext=len(value.split())
    value=value.split()
    for i in range(lentext-1):
        value.append("".join(value[i:i+2]))
    train_bigram.append(" ".join(value))
# output
  ['我 爱 北 京 天 安 门 我爱 爱北 北京 京天 天安 安门', '我 喜 欢 上 海 我喜 喜欢 欢上 上海']

4. TF-IDF:

TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。

我们的层级关系为:语料库>文档>词语。
\text{TF}_w(t)= \frac{该词语(w)在当前文档(t)出现的次数 }{ 当前文档(t)中词语的总数} \\ \text{IDF}_w(t)= ln (\frac{语料库中的文档总数 }{出现过该词语(w)的文档总数+ \epsilon })\\ \text{TF-IDF}_w(t) = \text{TF}_w(t)*\text{IDF}_w(t)

  • TF (term frequency)词频:
    指的是某一个给定的词语在该文档中出现的次数。
    这个数字通常会被归一化(一般是词频 除以文档总词数 ), 以防止它偏向长的文档。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)
  • IDF (inverse document frequency) 逆向文件频率:
    主要思想是:如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再取对数得到。

某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤常见的词语,保留重要的词语。

from sklearn.feature_extraction.text import TfidfVectorizer

由于TfidfVectorizerTfidf+CountVectorizer,所以有如下参数,
参数ngram_range: tuple(min_n, max_n):控制n-gram的范围,要提取的n-gram的n-values的下限和上限范围,在min_n <= n <= max_n区间的n的全部值。
参数max_features: 如果不为None,构建一个词汇表,仅考虑max_features--按语料词频排序,如果词汇表不为None,这个参数被忽略。也就是说这个参数可以加快运算速度。

TF-IDF的缺点主要还是稀疏的,维度也比较高
它使用sparse matrix进行保存数据的,简单的来说,就是三元组记录(i,j,k)表示 i 行 j 列的元素是 k 。

下面进行一下TF-IDF中元素的可视化展示:

首先是对象的类型:我们可以看到的确是sparse matrix,储存了53151659个元素

<200000x1000 sparse matrix of type '<class 'numpy.float64'>'
    with 53151659 stored elements in Compressed Sparse Row format>

矩阵train_test有什么特点? 计算一下它的稀疏度,达到了0.734,非常多的0啊。

# TODO: 
sparsity = 1- len(np.nonzero(train_test)[0])/(train_test.shape[0]*train_test.shape[1])
print (sparsity)  # 打印出稀疏度(sparsity)
#output
0.7342417050000001

我们取了每篇文章的前40个词语,为0不展示,非0输出。

for i in range(0,2):#打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重
    print (u"-------这里输出第",i+1,u"类文本的词语tf-idf权重------")
    for j in range(min(40,len(tfidf.get_feature_names()))):
        if train_test[i,j]!=0:
            print (tfidf.get_feature_names()[j],":",train_test[i,j])

output: 可以看到,前两篇文章只有不到10个是非0,可见tf-idf相当的稀疏啊

-------这里输出第 1 类文本的词语tf-idf权重------
1031 : 0.013883565340423655
1031 761 : 0.016471070579437433
1099 : 0.11356808782732254
1141 : 0.02594605663786779
1214 : 0.018628590967992242
1219 : 0.09588359370454744
1241 : 0.015350624386514937
1271 : 0.02999935826444165
1279 : 0.027819888128774638
1279 2975 : 0.01707749756960527
1324 : 0.00921777596903975
-------这里输出第 2 类文本的词语tf-idf权重------
1277 : 0.02127605710091801
1308 : 0.03284026507040861

5. 分布式表示:

关于文本的分布式表示留到下一次分享。

机器学习模型

1. RidgeClassifier:

这是教材中使用的模型为RidgeClassifier,属于sklearn.linear_model

对他和正则化的LogisticRegression的区别有一些疑问,后来查询资料后得知,他与正则化的LogisticRegression的区别是损失函数不同。

正则化的LogisticRegression的损失函数为cross-entropy,而RidgeClassifie 用了 Ridge的回归模型来建立一个分类器,损失函数为 RMSE + l2 penality。对于两分类,大于0为正例,小于0为负例。对于多分类,会使用One-Vs-Rest model对每一个分类进行预测,然后再合起来进行多分类的预测。

2. LogisticRegression:

关于LogisticRegression正好也写过一篇博客

本章作业

1. 尝试改变TF-IDF的参数,并验证精度

发现DSW压根跑不动全部数据集,自己的电脑有点心疼,还是取小点把,总之,tf-idfmaxfeature太大跑不动,太小没精度,真是个糟糕的词嵌入啊!

tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=1000)
train_test = tfidf.fit_transform(train['text'])

2.尝试使用其他机器学习模型,完成训练和验证

对于这么大的稀疏数据,根据CTR模型中的GBDT+LR模型的理论,LR模型对于稀疏数据的感觉会好一点,这里单选LR模型,不然DSW跑不动了。

X = train_test
y = np.array(train['label'])
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=666)
model = LogisticRegression(C=2.0)
model.fit(X_train,y_train)
y_predict = model.predict(X_test)
print(f1_score(y_predict, y_test, average='macro'))
# output 
0.8957692040204028

这里只是做了一些小尝试,也算是理解了文本表示中的离散模型,但是本人对tf-idf并不感兴趣,不想投入过多的算力在其中(抱紧自己的小电脑),期望在分布式表示中继续学习。

其他:

我们可以学习一个天池上面的baseline,来加深tf-idf+machine-learning的理解。
学习一个文本分类的baseline

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容