NLP到Word2Vec实战-第一课

文章目录

  • QA
  • NLTK
  • 一、概述
    • 1.定义
    • 2.安装NLTK
    • 3.安装语料库
  • 二、文本处理流程
    • 1.Tokenize——长句拆分成小部分
    • 2.中英文区别—中文没有空格
      • (1) 中文分词——jieba.cut()——一般要与''.join()连用
    • 3.处理特殊的字符串、表情符等——特殊符号的分词工具:re
    • 4.词形归一化
      • (1)Stemming 词⼲提取**PorterStemmer/SnowballStemmer/LancasterStemmer**
      • (2)Lemmatization 词形归⼀ **WordNetLemmatizer**
    • 5.标注
        • ①NLTK标注POS Tag
    • 6、NLTK去除stopwords
  • 三、NLTK在NLP上的应用
    • 1.情感分析
      • (1)简单的情感分析
      • (2)配上ML的情感分析
    • 2.文本相似度
      • (1)用元素频率表示文本特征
      • (2)余弦定理
      • (3)频率统计Frequency
    • 3.文本分类
      • (1)TF_IDF
        • ①**TF: Term Frequency**衡量⼀个term在⽂档中出现得有多频繁。
        • ②**IDF: Inverse Document Frequency** 衡量⼀个term有多重要。
        • ③IDF(t) = log_e(⽂档总数 / 含有t的⽂档总数).
        • ④**TF-IDF = TF \* IDF**
      • (2)NLTK实现TF-IDF TextCollection

QA

1.FreqDist和 TextCollection区别

FreqDist:单句处理

TextCollection:处理整个文档,一个list形式

NLTK

一、概述

1.定义

NLTK只是一套算法

Python上著名的⾃然语⾔处理库

⾃带语料库,词性分类库

⾃带分类,分词,等等功能

2.安装NLTK

# Mac/Unix

# Mac/Unix
sudo pip install -U nltk

# 顺便还可以装个Numpy
sudo pip install -U numpy

# 测试是否安装成功
>>> python
>>> import nltk

3.安装语料库

import nltk 

nltk.download()

corpus是语料,就是计算机多看到这些语料,才能学习到

tokenize是分词

可以在download(’ ‘ )在引号里面选择要下载的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wo4ZpkW3-1642387207196)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220112153846661.png)]

>>> from nltk.corpus import brown 
>>> brown.categories() 
['adventure', 'belles_lettres', 'editorial', 
'fiction', 'government', 'hobbies', 'humor', 
'learned', 'lore', 'mystery', 'news', 'religion', 
'reviews', 'romance', 'science_fiction'] 
>>> len(brown.sents()) 
57340
>>> len(brown.words()) 
1161192

二、文本处理流程

把一句话

预处理(很多流程)

​ 分词(将进来的词分成小块,在计算机里面的代表不同的位置)

​ 告诉他hello和from是不同的东西

特征工程:——将人理解的文本变为计算机能够看得懂的–创造不同的特征–比如文本变数字

机器学习:

1.Tokenize——长句拆分成小部分

>>> import nltk
>>> sentence = “hello, world"
>>> tokens = nltk.word_tokenize(sentence)
>>> tokens
['hello',,', 'world']

分词后的效果

2.中英文区别—中文没有空格

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FiX1fulZ-1642387207197)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220112154027659.png)]

(1) 中文分词——jieba.cut()——一般要与’’.join()连用

import jieba
seg_list = jieba.cut("我来到北京清华⼤学", cut_all=True)
print "Full Mode:", "/ ".join(seg_list) # 全模式

seg_list = jieba.cut("我来到北京清华⼤学", cut_all=False)
print "Default Mode:", "/ ".join(seg_list) # 精确模式

seg_list = jieba.cut("他来到了⽹易杭研⼤厦") # 默认是精确模式
print ", ".join(seg_list)

seg_list = jieba.cut_for_search("⼩明硕⼠毕业于中国科学院计算所,后在⽇本京都⼤学深造") 
# 搜索引擎模式
print ", ".join(seg_list)
"""
【全模式】: 我/ 来到/ 北京/ 清华/ 清华⼤学/ 华⼤/ ⼤学
【精确模式】: 我/ 来到/ 北京/ 清华⼤学
【新词识别】:他, 来到, 了, ⽹易, 杭研, ⼤厦
(此处,“杭研”并没有在词典中,但是也被Viterbi算法识别出来了) 
【搜索引擎模式】: ⼩明, 硕⼠, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 
计算所, 后, 在, ⽇本, 京都, ⼤学, ⽇本京都⼤学, 深造
"""

3.处理特殊的字符串、表情符等——特殊符号的分词工具:re

拯救 @某⼈, 表情符号, URL, #话题符号

from nltk.tokenize import word_tokenize
tweet = 'RT @angelababy: love you baby! :D http://ah.love #168cm'
print(word_tokenize(tweet))
# ['RT', '@', 'angelababy', ':', 'love', 'you', 'baby', '!', ':', 
# ’D', 'http', ':', '//ah.love', '#', '168cm']
import re
emoticons_str = r"""
 (?:
 [:=;] # 眼睛
 [oO\-]? # ⿐⼦
 [D\)\]\(\]/\\OpP] # 嘴
 )"""
regex_str = [
 emoticons_str,
 r'<[^>]+>', # HTML tags
 r'(?:@[\w_]+)', # @某⼈
 r"(?:\#+[\w_]+[\w\'_\-]*[\w_]+)", # 话题标签
 r'http[s]?://(?:[a-z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-f][0-9a-f]))+', 
# URLs
 r'(?:(?:\d+,?)+(?:\.?\d+)?)', # 数字
 r"(?:[a-z][a-z'\-_]+[a-z])", # 含有 - 和 ‘ 的单词
 r'(?:[\w_]+)', # 其他
 r'(?:\S)' # 其他
]

4.词形归一化

Inflection变化: walk => walking => walked 不影响词性

derivation 引申: nation (noun) => national (adjective) => nationalize (verb) 影响词性

(1)Stemming 词⼲提取PorterStemmer/SnowballStemmer/LancasterStemmer

⼀般来说,就是把不影响词性的inflection的⼩尾巴砍掉

walking 砍ing = walk

walked 砍ed = walk

>>> from nltk.stem.porter import PorterStemmer
>>> porter_stemmer = PorterStemmer()
>>> porter_stemmer.stem(‘maximum’)
u’maximum’
>>> porter_stemmer.stem(‘presumably’)
u’presum’
>>> porter_stemmer.stem(‘multiply’)
u’multipli’
>>> porter_stemmer.stem(‘provision’)
u’provis’

>>> from nltk.stem import SnowballStemmer
>>> snowball_stemmer = SnowballStemmer(“english”)
>>> snowball_stemmer.stem(‘maximum’)
u’maximum’
>>> snowball_stemmer.stem(‘presumably’)
u’presum’
>>> from nltk.stem.lancaster import LancasterStemmer
>>> lancaster_stemmer = LancasterStemmer()
>>> lancaster_stemmer.stem(‘maximum’)
‘maxim’
>>> lancaster_stemmer.stem(‘presumably’)
‘presum’
>>> lancaster_stemmer.stem(‘presumably’)
‘presum’

>>> from nltk.stem.porter import PorterStemmer
>>> p = PorterStemmer()
>>> p.stem('went')
'went'
>>> p.stem('wenting')
'went'

(2)Lemmatization 词形归⼀ WordNetLemmatizer

①把各种类型的词的变形,都归为⼀个形式

went 归⼀ = go

are 归⼀ = be

>>> from nltk.stem import WordNetLemmatizer
>>> wordnet_lemmatizer = WordNetLemmatizer()
>>> wordnet_lemmatizer.lemmatize(‘dogs’)
u’dog’
>>> wordnet_lemmatizer.lemmatize(‘churches’)
u’church’
>>> wordnet_lemmatizer.lemmatize(‘aardwolves’)
u’aardwolf’
>>> wordnet_lemmatizer.lemmatize(‘abaci’)
u’abacus’
>>> wordnet_lemmatizer.lemmatize(‘hardrock’)
‘hardrock’

5.标注

# ⽊有POS Tag,默认是NN 名词
>>> wordnet_lemmatizer.lemmatize(‘are’)
‘are’
>>> wordnet_lemmatizer.lemmatize(is)is# 加上POS Tag
>>> wordnet_lemmatizer.lemmatize(is, pos=’v’)
u’be’
>>> wordnet_lemmatizer.lemmatize(‘are’, pos=’v’)
u’be’

①NLTK标注POS Tag

>>> import nltk
>>> text = nltk.word_tokenize('what does the fox say')
>>> text
['what', 'does', 'the', 'fox', 'say']
>>> nltk.pos_tag(text)
[('what', 'WDT'), ('does', 'VBZ'), ('the', 'DT'), ('fox', 'NNS'), ('say', 'VBP')]

6、NLTK去除stopwords

from nltk.corpus import stopwords
# 先token⼀把,得到⼀个word_list
# 然后filter⼀把
filtered_words = 
[word for word in word_list if word not in stopwords.words('english')]

三、NLTK在NLP上的应用

1.情感分析

(1)简单的情感分析

sentiment_dictionary = {}
for line in open('data/AFINN-111.txt'):
  word, score = line.split('\t')
	sentiment_dictionary[word] = int(score)
# 把这个打分表记录在⼀个Dict上以后
# 跑⼀遍整个句⼦,把对应的值相加
total_score = sum(sentiment_dictionary.get(word, 0) for word in words)
# 有值就是Dict中的值,没有就是0
# 于是你就得到了⼀个 sentiment score

(2)配上ML的情感分析

这些单词是不是在句子里面出现过,

from nltk.classify import NaiveBayesClassifier

# 随⼿造点训练集
s1 = 'this is a good book'
s2 = 'this is a awesome book'
s3 = 'this is a bad book'
s4 = 'this is a terrible book'

def preprocess(s):
# Func: 句⼦处理
# 这⾥简单的⽤了split(), 把句⼦中每个单词分开
# 显然 还有更多的processing method可以⽤
		return {word: True for word in s.lower().split()}

# return⻓这样:
# {'this': True, 'is':True, 'a':True, 'good':True, 'book':True}
# 其中, 前⼀个叫fname, 对应每个出现的⽂本单词;
# 后⼀个叫fval, 指的是每个⽂本单词对应的值。
# 这⾥我们⽤最简单的True,来表示,这个词『出现在当前的句⼦中』的意义。
# 当然啦, 我们以后可以升级这个⽅程, 让它带有更加⽜逼的fval, ⽐如 word2vec

2.文本相似度

(1)用元素频率表示文本特征

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WmT33E0O-1642387207198)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117092643370.png)]

第一句话:we在文本中出现了1次,you出现0次,he出现3次

(2)余弦定理

夹角越小

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2vEf3Qx-1642387207201)(/Users/duanyuqing/Library/Application Support/typora-user-images/image-20220117092707395.png)]

(3)频率统计Frequency

FreqDist统计器:在token中做统计

第一步:word_tokenize或者jieba进行分词,分成一个word list

第二步:用FreqDist统计,直接将分完词的tokens放进去,就可以得到出现多少次了

第三步:most_common取出最常用的单词,是一个长的列表,记录下size,做特征向量

import nltk
from nltk import FreqDist
# 做个词库先
corpus = 'this is my sentence ' ,'this is my life ' ,'this is the day'

# 随便tokenize⼀下
# 显然, 正如上⽂提到,这⾥可以根据需要做任何的preprocessing:
# stopwords, lemma, stemming, etc.

tokens = nltk.word_tokenize(corpus)
print(tokens)
# 得到token好的word list
# ['this', 'is', 'my', 'sentence','this', 'is', 'my', 'life', 'this','is', 'the', 'day']
# 借⽤NLTK的FreqDist统计⼀下⽂字出现的频率

fdist = FreqDist(tokens)
# 它就类似于⼀个Dict
# 带上某个单词, 可以看到它在整个⽂章中出现的次数

print(fdist['is'])
# 3
# 好, 此刻, 我们可以把最常⽤的50个单词拿出来
standard_freq_vector = fdist.most_common(50)
size = len(standard_freq_vector)
print(standard_freq_vector)
# [('is', 3), ('this', 3), ('my', 2),
# ('the', 1), ('day', 1), ('sentence', 1),
# ('life', 1)

第四步:position_lookup确定每个单词的位置,这样才能保证向量之间计算的时候没有偏值

第五步:把标准的单词位置记录下来

# Func: 按照出现频率⼤⼩, 记录下每⼀个单词的位置
def position_lookup(v):
  res = {}
  counter = 0
  for word in v:
    res[word[0]] = counter
    counter += 1
   return res
# 把标准的单词位置记录下来
standard_position_dict = position_lookup(standard_freq_vector)
print(standard_position_dict)
# 得到⼀个位置对照表
# {'is': 0, 'the': 3, 'day': 4, 'this': 1,
# 'sentence': 5, 'my': 2, 'life': 6}

第六步:新建⼀个跟我们的标准vector同样⼤⼩的向量

第七步:作为x带入

# 这时, 如果我们有个新句⼦:
sentence = 'this is cool'

# 先新建⼀个跟我们的标准vector同样⼤⼩的向量
freq_vector = [0] * size

# 简单的Preprocessing
tokens = nltk.word_tokenize(sentence)

# 对于这个新句⼦⾥的每⼀个单词
for word in tokens:
  try:
# 如果在我们的词库⾥出现过
# 那么就在"标准位置"上+1
		freq_vector[standard_position_dict[word]] += 1
  except KeyError:
# 如果是个新词
# 就pass掉
		continue
  
print(freq_vector)
# [1, 1, 0, 0, 0, 0, 0]
# 第⼀个位置代表 is, 出现了⼀次
# 第⼆个位置代表 this, 出现了⼀次
# 后⾯都⽊有

3.文本分类

(1)TF_IDF

TF: Term Frequency衡量⼀个term在⽂档中出现得有多频繁。

TF(t) = (t出现在⽂档中的次数) / (⽂档中的term总数).

IDF: Inverse Document Frequency 衡量⼀个term有多重要。

有些词出现的很多,但是明显不是很有卵⽤。⽐如’is’,’the‘,’and‘之类的。

为了平衡,我们把罕见的词的重要性(weight)搞⾼,

把常见词的重要性搞低。

③IDF(t) = log_e(⽂档总数 / 含有t的⽂档总数).

TF-IDF = TF * IDF

eg:

⼀个⽂档有100个单词,其中单词baby出现了3次。

那么,TF(baby) = (3/100) = 0.03.

好,现在我们如果有10M的⽂档, baby出现在其中的1000个⽂档中。

那么,IDF(baby) = log(10,000,000 / 1,000) = 4

所以, TF-IDF(baby) = TF(baby) * IDF(baby) = 0.03 * 4 = 0.12

(2)NLTK实现TF-IDF TextCollection

from nltk.text import TextCollection
# ⾸先, 把所有的⽂档放到TextCollection类中。
# 这个类会⾃动帮你断句, 做统计, 做计算

corpus = TextCollection(['this is sentence one', 'this is sentence two', 
'this is sentence three'])
# 直接就能算出tfidf
# (term: ⼀句话中的某个term, text: 这句话)

print(corpus.tf_idf('this', 'this is sentence four'))
# 0.444342
# 同理, 怎么得到⼀个标准⼤⼩的vector来表示所有的句⼦?
# 对于每个新句⼦

new_sentence = 'this is sentence five'
# 遍历⼀遍所有的vocabulary中的词:

for word in standard_vocab:
	print(corpus.tf_idf(word, new_sentence))
# 我们会得到⼀个巨⻓(=所有vocab⻓度)的向量

你可能感兴趣的:(自然语言处理,自然语言处理,word2vec,python)