nlp入门(一) :nlp常用工具包实战
源码请到:自然语言处理练习: 学习自然语言处理时候写的一些代码 (gitee.com)
一、字符串处理
这里是一些自然语言中常用的python字符串操作,python内置无需安装
1.1 strip函数:去掉首尾特定字符
示例:
text = " abcdef125s wr2258abcd " print("base", text) print("strip:", text.strip(" "))
1.2 rstrip函数和lstrip函数:去掉右边特定字符和去掉左边特定字符
示例:
print("lstrip:", text.lstrip(" ")) print("rstrip:", text.rstrip(" "))
1.3 replace函数:替换特定字符字串,可以传入参数确定替换字串的个数
示例:
print("replace:", text.replace('a', 'A')) print("replace:", text.replace('a', 'A', 1))
1.4 find函数:查找子串返回字串的下标位置,如果没有返回-1
示例:
print("find:", text.find('a'))
1.5 isalpha函数和isdigit函数:判断字符串是否全为字母和判断字符串是否全为数字
示例:
print("isalpha:", "abc -", "abc".isalpha(), "123 -", "123".isalpha(), "a123 -", "a123".isalpha()) print("isdigit:", "abc -", "abc".isdigit(), "123 -", "123".isdigit(), "a123 -", "a123".isdigit())
1.6 split函数:按照字串分割字符串
示例:
text2 = "a,d,dw,d,s,w,t,c,w," list1 = text2.split(',') print("base:", text2) print("split:", list1)
1.7 join函数:将字串列表按照特定字符间隔合并起来
示例:
print("join:", ",".join(list1))
二、正则表达式
python中还内置了re模块,可以使用正则表达式来进行数据的预处理,首先贴几张正则表达式语法表(摘自Python核心编程3rd)
2.1 将符合正则表达式的字符串匹配式传入re模块的compile函数,注意字符串前加r表示不使用转义字符,或者每个/写作//。
示例:
pattern = re.compile(r'\d+') print("正则表达式:", re.findall(pattern, text))
2.2 match函数和serch函数
两个函数都是查找是否有符合正则表达式的字串,不同在于match函数是字串必须从字符串第一个开始就匹配,如果没有则返回none,search函数是从原字符串任意位置开始匹配都可以
示例:
print("match:", re.match(pattern, text)) print("serch:", re.search(pattern, text))
2.3 sub和subn函数
两个函数都是替换字符字串的功能,第二个函数会返回一个元组,元组中第二个参数表示替换了几处
示例:
print("sub:", re.sub(pattern, '*', text)) print("subn:", re.subn(pattern, '*', text))
2.4 split切片函数
通过匹配的正则表达式为依据进行切片
示例:
print("split", re.split(pattern, text))
三、nltk工具的使用
3.1 nltk工具的安装
使用命令
pip install nltk
安装nltk,但是仅仅是安装了nltk的框架,内部的软件包需要使用命令
nltk.download()
执行命令会弹出一个窗口
无法下载软件包的问题可以参考这篇:NLTK语料库nltk.download()安装失败及下载很慢的解决方法_深度学习菜鸟的博客-CSDN博客
将服务器地址改为了http://www.nltk.org/nltk_data/
就可以正常安装软件包了
3.2 nltk分词操作
安装成功后就可以使用分词器进行分词了
示例:
input_str = "Today's weather is good, very windy and sunny, we have no classes in the afternoon. We have to play " \ "basketball tomorrow" tokens = word_tokenize(input_str)
3.3 nltk简单文本操作
nltk可以进行一些简单的文本操作,如统计词的个数,查找词的位置等
示例:
# 文本操作 t = Text(tokens) print(t.count('good')) print(t.index('good')) print(t.plot())
3.4 停用词
出现频率很高但是对自然语言处理价值很低的词被叫做停用词
nltk自带了一些停用词表,输入命令就可以查看支持语言的停用词表
示例:
print(stopwords.fileids())
可以看到支持的语言不包含中文,所有接下来我们只使用英文语料库
输入命令就可以查看英文停用词表
示例:
print(stopwords.raw('english'))
数量很多就不全部展示了,接下来查找目前语料库中的停用词
print(test_words_set.intersection(set(stopwords.words('english'))))
为了进一步进行自然语言处理,很多时候我们需要将停用词进行筛除,nltk就可以做到这个功能。
示例:
filterd = [w for w in test_words_set if w not in stopwords.words('english')] print(filterd)
3.5 词性标注
nltk还可以将每个词的词性标注出来,词性表如下
示例:
tags = pos_tag(tokens) print(tags)
3.6 分块
可以根据词性对词进行分块
示例:
我定义了一个MY_NP的词并且用正则表达式写出这个块的句子词性是什么样的,nltk可以找出语料库中符合的块
sentence = [('the', 'DT'), ('little', 'JJ'), ('yellow', 'JJ'), ('dog', 'NN'), ('died', 'VBD')] grammer = "MY_NP: {<DT>?<JJ>*<NN>}" cp = nltk.RegexpParser(grammer) result = cp.parse(sentence)
3.7 命名实体识别
nltk可以提取出一些语句中的实体
示例:
# 命名实体识别 sentence = "Edison went to Tsinghua University today" print(ne_chunk(pos_tag(word_tokenize(sentence))))
Edison被识别出是个人,清华大学被识别出是个组织
3.8 数据清洗
网络上爬取的语料中有可能有很多特殊符号,对nlp造成了很大的影响,所以需要一些方法来进行数据清理,利用nltk可以很好的办到这些
示例:
# 数据清洗 s = "RT @Amila #Test\nTom\'s newly listed Co & Mary\'s unlisted Group to supply tech for nlTK.\nh $TSLA " \ "$AAPL https:// t.co/x34afsfQsh" cache_english_stopwords = stopwords.words('english') def text_clean(text): print('原始数据:', text, "\n") # 去掉HTML标签(e.g. &) text_no_special_entities = re.sub(r'&\w*;|#\w*|@\w*', '', text) print("去掉特殊标签后的:", text_no_special_entities, '\n') # 去掉一些价值符号 text_no_tickers = re.sub(r'\$\w*', '', text_no_special_entities) print("去掉一些价值符号的:", text_no_tickers, '\n') # 去掉超链接 text_no_hyperlinks = re.sub(r'https?://.*/\w*', '', text_no_tickers) print("去掉超链接的:", text_no_hyperlinks, '\n') # 去掉一些专门名词缩写,简单来说就是字母较少的词 text_no_small_words = re.sub(r'\b\w{1,2}\b', '', text_no_hyperlinks) print("去掉专门名词缩写的:", text_no_small_words, '\n') # 去掉多余空格 text_no_whitespace = re.sub(r'\s\s+', " ", text_no_small_words) text_no_whitespace = text_no_whitespace.lstrip(' ') print("去掉多余空格的:", text_no_whitespace, '\n') # 分词 tokens = word_tokenize(text_no_whitespace) print("分词结果:", tokens, '\n') # 去停用词 list_no_stopwords = [i for i in tokens if i not in cache_english_stopwords] print('去掉停用词结果', list_no_stopwords, '\n') # 过滤后结果 text_filtered = ' '.join(list_no_stopwords) print('过滤后', text_filtered) text_clean(s)
四、spacy工具包的使用
4.1 spacy工具包安装
spacy工具包宣称可以做到nltk做到的所有事情,并且速度更快,还更好的适配深度学习,最关键的是提供了中文语言模型!!
由于某些不可说的原因,使用官网的安装方式很难成功推荐直接使用conda内部的整合包
运行
conda install spacy
conda install -c conda-forge spacy-model-en_core_web_sm
就可以安装成功了
如果不成功可以网上寻找spacy的离线安装包,可以参考这篇文章
安装spaCy(最简单的教程)_spacy安装_御用厨师的博客-CSDN博客
4.2 加载模型
可以自行选择安装需要的模型,然后使用命令加载,我这里使用英文模型做示范
示例:
# 加载模型 nlp = spacy.load("en_core_web_sm")
4.3 分词
spacy同样可以做到分词
示例:
# 加载语料 doc = nlp('Weather is good, very windy and sunny. We have no classes in the afternoon') # 分词 for token in doc: print(token)
4.4 分句
spacy还提供了分句功能
示例:
# 分句 for sent in doc.sents: print(sent)
4.5 词性
spacy和nltk一样提供了分析词性的功能
示例:
# 词性 for token in doc: print('{}-{}'.format(token, token.pos_))
词性对照表可以参考
4.6 命名体识别
spacy也提供了命名体识别功能
示例:
# 命名体识别 doc_2 = nlp("I went to Paris where I met my old friend Jack from uni") for ent in doc_2.ents: print('{}-{}'.format(ent, ent.label_))
还可以将结果进行可视化展示
# 展示 doc = nlp("I went to Paris where I met my old friend Jack from uni") svg = displacy.render(doc, style='ent') output_path = Path(os.path.join("./", "sentence.html")) output_path.open('w', encoding="utf-8").write(svg)
4.7 找出书中所有人物的名字
以傲慢与偏见为语料,做一个找出所有人物名字的实战示例
示例:
# 找到书中所有人物名字 def read_file(file_name): with open(file_name, 'r') as f: return f.read() text = read_file(os.path.join('./', 'data/Pride and Prejudice.txt')) processed_text = nlp(text) sentences = [s for s in processed_text.sents] print(len(sentences)) print(sentences[:5]) def find_person(doc): c = Counter() for ent in doc.ents: if ent.label_ == 'PERSON': c[ent.lemma_] += 1 return c.most_common(10) print(find_person(processed_text))
4.8 恐怖袭击分析
根据世界反恐怖组织官网上下载的恐怖袭击事件,来分析特定的组织在特定的地点作案的次数
示例:
# 恐怖袭击分析 def read_file_to_list(file_name): with open(file_name, 'r') as f: return f.readlines() terrorist_articles = read_file_to_list(os.path.join('./', 'data/rand-terrorism-dataset.txt')) print(terrorist_articles[:5]) terrorist_articles_nlp = [nlp(art.lower()) for art in terrorist_articles] common_terrorist_groups = [ 'taliban', 'al-qaeda', 'hamas', 'fatah', 'plo', 'bilad al-rafidayn' ] commmon_locations = [ 'iraq', 'baghdad', 'kirkuk', 'mosul', 'afghanistan', 'kabul', 'basra', 'palestine', 'gaza', 'israel', 'istanbul', 'beirut', 'pakistan' ] location_entity_dict = defaultdict(Counter) for article in terrorist_articles_nlp: article_terrorist_groups = [ent.lemma_ for ent in article.ents if ent.label_ == 'PERSON' or ent.label_ == "ORG"] article_locations = [ent.lemma_ for ent in article.ents if ent.label_ == 'GPE'] terrorist_common = [ent for ent in article_terrorist_groups if ent in common_terrorist_groups] location_common = [ent for ent in article_locations if ent in commmon_locations] for found_entity in terrorist_common: for found_location in location_common: location_entity_dict[found_entity][found_location] += 1 print(location_entity_dict) location_entity_df = pd.DataFrame.from_dict(dict(location_entity_dict), dtype=int) location_entity_df = location_entity_df.fillna(value=0).astype(int) print(location_entity_df) plt.figure(figsize=(12, 10)) hmap = sns.heatmap(location_entity_df, annot=True, fmt='d', cmap='YlGnBu', cbar=False) plt.title("Global Incidents by Terrorist group") plt.xticks(rotation=30) plt.show()
五、jieba分词器
说到中文分词,就不得不提jieba分词器,虽然已经很久没有更新,但是依然很好用
5.1 jieba分词器安装
jieba分词器安装十分方便,输入命令就可安装成功
pip install jieba
5.2 分词工具
jieba分词器提供了中文的分词工具,并且有精确模式和全模式两种模式,默认是精确模式
示例:
# 分词工具 seg_list = jieba.cut('我来到北京清华大学', cut_all=True) print('全模式:' + '/'.join(seg_list)) seg_list = jieba.cut('我来到北京清华大学', cut_all=False) print('精确模式:' + '/'.join(seg_list)) seg_list = jieba.cut('他来到网易杭研究大厦') print(','.join(seg_list))
5.3 添加自定义词典
jieba还可以添加自定义的词典,使分词更精准
示例:
# 添加自定义词典 text = '故宫的著名景点包括乾清宫、太和殿和黄琉璃瓦等' seg_list = jieba.cut(text, cut_all=True) print('全模式:' + '/'.join(seg_list)) seg_list = jieba.cut(text, cut_all=False) print('精确模式:' + '/'.join(seg_list))
默认词典中不识别乾清宫和黄琉璃瓦,现在添加词典加入这两个词
jieba.load_userdict("./data/mydict.txt") # jieba.add_word("乾清宫") text = '故宫的著名景点包括乾清宫、太和殿和黄琉璃瓦等' seg_list = jieba.cut(text, cut_all=True) print('全模式:' + '/'.join(seg_list)) seg_list = jieba.cut(text, cut_all=False) print('精确模式:' + '/'.join(seg_list))
5.4 关键字提取
根据词典中词语的频率,可以提取关键词
示例:
# 关键字抽取 seg_list = jieba.cut(text, cut_all=False) print(u"分词结果:") print('/'.join(seg_list)) tags = jieba.analyse.extract_tags(text, topK=5) print(u"关键字:") print(' '.join(tags)) tags = jieba.analyse.extract_tags(text, topK=5, withWeight=True) for word, weight in tags: print(word, weight)
5.5 词性标注
jieba也可以标注词性
示例:
# 词性标注 words = pseg.cut('我爱北京天安门') for word, flag in words: print('%s %s' % (word, flag))
5.6 词云展示
利用十九大***的发言稿作为语料,进行分词并且统计频率最后画在一张图上体现出来关键字
示例
# 词云展示 data = {} with open('./data/19Congress.txt', 'r', encoding='utf-8') as f: text = f.read() with open('./data/stopwords.txt', encoding='utf-8') as file: stopwords = [line.strip() for line in file] seg_list = jieba.cut(text, cut_all=False) for word in seg_list: if len(word) >= 2: if not data.__contains__(word): data[word] = 0 data[word] += 1 print(data) my_wordclod = WordCloud( background_color='white', # 背景颜色 max_words=400, # 设置最大实现的字数 font_path=r'./data/SimHei.ttf', # 设置字体格式,不设置显示不了中文 mask=imread('./data/mapofChina.jpg'), # 指定在什么图片上画 width=1000, height=1000, stopwords=set(stopwords) ).generate_from_frequencies(data) plt.figure(figsize=(18,16)) plt.imshow(my_wordclod) plt.axis('off') plt.show() my_wordclod.to_file('result.jpg')
其中原图是一张纯色的中国地图
运行后的结果