今天是2021年10月6日,从9月份开学好像一直什么都没有学习,可能也只有每天刷点力扣题了吧,一天当中很多的时间都浪费了,本来想的是平平淡淡的过完研究生的生活,但好像发现如果一开始的目标就很低的话,那很可能这个目标完成不了,所以说我的目标就是成为优秀毕业生顺利毕业,与此同时希望自己能找到一个好工作。
那么从现在开始,我不仅仅要每天刷力扣题,而且还要准备论文和项目了,java方面的我是不太可能了,因为对此没有一点兴趣,所以还是选择python吧,计算机视觉方面的不管是图像识别、图像分割等等相对来说都是比较成熟的,也很难做出一些什么来,当然,这可能也是我在为自己找借口,但是计算机视觉的应用还是很多的,所以暂时先默认自己会用那些东西了,转战NLP,特别是文本方向。
入门博客:https://www.jianshu.com/p/b87e01374a65
有帮助的博客:https://blog.csdn.net/md_Ji/article/details/112688029
语料库:http://www.sogou.com/labs/resource/ca.php(直接下载到本地就行,解压缩就是.dat文件,在python中可以直接读)
我们下载好搜狗新闻的语料库之后,会发现我们的数据是这样的:
http://news.163.com/12/0727/13/87E4GD4600014JB5.html
c3a2c1b2db10c944-b345d9a362314a50
宏皓:中国企业如何应对奥运赛场外的"品宣战"
用以下代码读取数据:
import codecs
import re
from tqdm import tqdm
file_path=r"D:\pythonworkspace\NLP_project\news_tensite_xml.dat" #原始的语料信息
save_path=r"D:\pythonworkspace\NLP_project\SougouNews_dataset.txt" #处理后只有文章内容的语料
seg_save_path=r"D:\pythonworkspace\NLP_project\SougouNews_daraset_Seg.txt" #文章内容分析后的语料
#read file
print("read news dataset:",file_path)
with open(file_path, encoding='gb18030') as f:
news_data = f.read().encode('gbk', 'ignore').decode('gbk')
#print(news_data)
读取完之后,就要进行下一步的工作了。
file_path=r"D:\pythonworkspace\NLP_project\news_tensite_xml.dat" #原始的语料信息
save_path=r"D:\pythonworkspace\NLP_project\SougouNews_dataset.txt" #处理后只有文章内容的语料
seg_save_path=r"D:\pythonworkspace\NLP_project\SougouNews_daraset_Seg.txt" #文章内容分析后的语料
数据清洗,就是在语料中找到我们感兴趣的东西,把不感兴趣的、视为噪音的内容清洗删除,包括对于原始文本提取标题、摘要、正文等信息,对于爬取的网页内容,去除广告、标签、HTML、JS 等代码和注释等。
常见的数据清洗方式有:人工去重、对齐、删除和标注等,或者规则提取内容、正则表达式匹配、根据词性和命名实体提取、编写脚本或者代码批处理等。
在这个例子中,我们所说的语料清洗,指的就是只获取content标签之间的内容:
#抽取content之间的内容(即 预料清洗)
print("extract news content....")
news_content = re.findall('.* ',news_data)
#将刚才处理好的只有文本内容的语料存入刚才设定的文件夹中
print("write content to text file ...")
with codecs.open(save_path, 'w', encoding='utf8') as fw:
# 注意tqdm只是一个进度条 也可以不需要
for item in tqdm(news_content):
item = re.sub(r'| |\s', '', item)
# item = stringQ2B(item) # 全部全角转半角
item = stringpartQ2B(item) # 只有数字字母全角转半角
if item != "":
fw.write(item + '\n')
可以看到上面有两个函数:stringQ2B和stringpartQ2B这两个函数是处理文本内容的,具体的我还没有看,等回头看了再重新写个专题补上:
def is_Qnumber(uchar):
"""判断一个unicode是否是全角数字"""
if uchar >= u'\uff10' and uchar <= u'\uff19':
return True
else:
return False
def is_Qalphabet(uchar):
"""判断一个unicode是否是全角英文字母"""
if (uchar >= u'\uff21' and uchar <= u'\uff3a') or (uchar >= u'\uff41' and uchar <= u'\uff5a'):
return True
else:
return False
def Q2B(uchar):
"""单个字符 全角转半角"""
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e: #转完之后不是半角字符返回原来的字符
return uchar
return chr(inside_code)
def stringQ2B(ustring):
"""把字符串全角转半角"""
return "".join([Q2B(uchar) for uchar in ustring])
def stringpartQ2B(ustring):
"""把字符串中数字和字母全角转半角"""
return "".join([Q2B(uchar) if is_Qnumber(uchar) or is_Qalphabet(uchar) else uchar for uchar in ustring])
分词可以直接用python中的jieba库:
with codecs.open(seg_save_path, 'w', encoding='utf8') as fw:
for content in tqdm(news_content):
content = re.sub(r'| |\s', '', content)
# content = stringQ2B(content) # 全部全角转半角
item = stringpartQ2B(item) # 只有数字字母全角转半角
if content != "":
# 这里分词调用的是jieba 也可以使用其它分词工具
content_seg = jieba.cut(content.strip())
fw.write(" ".join(content_seg) + "\n")
词性标注和去停用词还没有动手去实践,所以在这里先不写。
这里有一个详细讲解各种预处理的博客:https://blog.csdn.net/qq_35273499/article/details/79098689
做完语料预处理之后,接下来需要考虑如何把分词之后的字和词语表示成计算机能够计算的类型。显然,如果要计算我们至少需要把中文分词的字符串转换成数字,确切的说应该是数学中的向量。有两种常用的表示模型分别是词袋模型和词向量。
即不考虑词语原本在句子中的顺序,直接将每一个词语或者符号统一放置在一个集合(如 list),然后按照计数的方式对出现的次数进行统计。统计词频这只是最基本的方式,TF-IDF 是词袋模型的一个经典用法。
词向量是将字、词语转换成向量矩阵的计算模型。目前为止最常用的词表示方法是 One-hot,这种方法把每个词表示为一个很长的向量。这个向量的维度是词表大小,其中绝大多数元素为 0,只有一个维度的值为 1,这个维度就代表了当前的词。
还有 Google 团队的 Word2Vec,其主要包含两个模型:跳字模型(Skip-Gram)和连续词袋模型(Continuous Bag of Words,简称 CBOW)。
以及两种高效训练的方法:负采样(Negative Sampling)和层序 Softmax(Hierarchical Softmax)。值得一提的是,Word2Vec 词向量可以较好地表达不同词之间的相似和类比关系。除此之外,还有一些词向量的表示方式,如 Doc2Vec、WordRank 和 FastText 等。
这个后面肯定是还要再学习的,只不过在今天,也学习了一点,就是说在对语料进行预处理之后,我们就可以构建词向量了,今天用的是word2vec模型,直接用gensim库中的word2vec函数就可以实现:
首先定义词向量模型的训练函数:
#NLP的基本处理步骤就是:首先获取语料库,然后对语料库进行语料的清洗、分词、去停用词等等一些预处理,那么在预处理之后
#我们就算是得到了要输入的数据的样子,那么怎么将数据转化为计算机可以看懂的呢?两种方法:词袋模型 、词向量
#由于这一part只是辅助我来理解NLP的一个大致过程,所以对于这两种方法先不去细细研究是怎么回事,就直接上代码去体会一下:
#以词向量为例子,用的是word2vec
import logging
import gensim.models as word2vec
from gensim.models.word2vec import LineSentence
def train_word2vec(dataset_path, model_path, size=100, window=5, binary=True):
#设置输出日志
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
# 把语料变成句子集合
sentences = LineSentence(dataset_path)
# 训练word2vec模型
model = word2vec.Word2Vec(sentences, window=window, min_count=5, workers=4)
# 保存word2vec模型
if binary:
model.wv.save_word2vec_format(model_path, binary=True)
else:
model.wv.save_word2vec_format(model_path, binary=False)
然后加载词向量模型,其实我一直对词向量模型都不太理解,但是今天实践了之后,我觉得和神经网络中的什么vgg,resnet其实都差不多,只不过是说我们训练的vgg和resnet之后,有一个权重保存为.h5文件了,模型本身是没有变的,而词向量模型就类似于神经网络模型中的权重文件,个人理解.
def load_word2vec_model(w2v_path){
# load word2vec
model = word2vec.KeyedVectors.load_word2vec_format(w2v_path, binary=True)
return model
}
dataset_path=r"D:\pythonworkspace\NLP_project\SougouNews_daraset_Seg.txt"
save_model_path =r"D:\pythonworkspace\NLP_project\word2vec_model.bin"
train_word2vec(dataset_path, save_model_path, size=100, window=5, binary=True)
当用word2vec训练完语料库的词向量之后,就可以用它来做一些事情了:
(1)找出某一词向量最相近的集合
(2)查看两个词向量的相近程度
(3)找出一组集合中不同的类别
#加载模型
model =load_word2vec_model("./word2vec_model.bin")
#应用
# (1)计算两个词向量的相似度
sim1 = model.similarity(u'美丽', u'漂亮')
print(u'美丽 和 漂亮 的相似度为 ', sim1)
# (2)与某个词(李达康)最相近的3个字的词
print(u'与北京最相近的3个字的词')
req_count = 5
for key in model.similar_by_word(u'北京', topn=100):
if len(key[0]) == 3:
req_count -= 1
print(key[0], key[1])
if req_count == 0:
break
# 计算某个词(侯亮平)的相关列表
print(u'和 新华社 与相关的词有:\n')
sim3 = model.most_similar(u'新华社', topn=5)
for key in sim3:
print(key[0], key[1])
# 找出不同类的词
sim4 = model.doesnt_match(u'北京 上海 人民 石家庄'.split())
print(u'北京 上海 人民 石家庄')
print(u'上述中不同类的名词', sim4)
结果:
美丽 和 漂亮 的相似度为 0.6385814
与北京最相近的3个字的词
石家庄 0.636853039264679
北京市 0.5878795385360718
哈尔滨 0.5805991888046265
北京站 0.5749763250350952
五棵松 0.5512964129447937
和 新华社 与相关的词有:
中新社 0.7977388501167297
新华网 0.6743009686470032
中新网 0.6310275793075562
胡续 0.6224453449249268
中国日报 0.6152859330177307
北京 上海 人民 石家庄
上述中不同类的名词 人民