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)
 print(tokens)

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  &amp; 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. &amp;)
    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_))

 词性对照表可以参考

SpaCy词性对照表 - 知乎 (zhihu.com)

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')

 其中原图是一张纯色的中国地图

 运行后的结果

 

posted @ 2023-07-31 10:23  过客匆匆,沉沉浮浮  阅读(398)  评论(0编辑  收藏  举报