非结构话数据到知识图谱
非结构数据-> 信息抽取(命名实体识别、关系抽取)-> 图谱构建(实体消歧、链接预测)-> 图分析算法
一、文本分析关键技术
- 拼写纠错
- 分词
- 词干提取
- 词的过滤
- 文本的表示
- 文本相似度
- 词向量
- 句子向量
- 实体命名识别
二、拼写纠错
input -> correction
天起 -> 天气
theris -> theirs
机器学系 -> 机器学习
找出编辑距离最小的
input candidates edit distance
therr there 1
thesis 3
theirs 2
the 2
their 1
计算编辑距离:
Given str s, str t => editDist(s,t)
算法原理:
"""代码实现"""
def edit_dist(str1,str2):
m,n = len(str1),len(str2)
dp = [[0 for x in range(n+1)] for x in range(m+1)]
for i in range(m+1):
for j in range(n+1):
if i == 0:
dp[i][j] = j
elif j == 0:
dp[i][j] = i
elif str1[i-1] == str2[j-1]:
dp[i][j] = dp[i-1][j-1]
else:
dp[i][j] = 1 + min(dp[i][j-1], dp[i-1,j-1], dp[i-1][j])
return dp[m][n]
根据之前的想法可以抽样为流程:用户输入-> 找出词典库中编辑距离最小的Top K -> 排序
缺点:跟每一个单词都要计算编辑距离-时间复杂度太高
改进后方案:
用户输入-> 生成编辑距离1,2的所有可能的字符串-> 通过词典过滤 -> 排序
生成的字符串远小于词典库
P(c)和P(s/c)可以基于统计方法计算出历史出现的概率值
三、分词
在很多语言中,分词是最为重要的第一步,如汉语,一般用jieba分词工具
怎么写一个分词工具?
简单两步骤:语句-> 候选分割(词典DP)-> 选择最好的(语言模型)
缺点:时间效率低、误差传递
改进:分割 + 语言模型 ->Joint optimization
"""jieba分词"""
import jieba
seg_list = jieba.cut("小王专注于人工智能",cut_all=False)
print(" ".join(seg_list))
"""增加词典"""
jieba.add_word("小王专注")
四、词的过滤
通常先把停用词、出现频率很低的词汇过滤掉
好处:提高准确率、减少时间成本
停用词(stop words)
英文中 比如 "the" "an" "their" 都可以作为停用词来处理。但是也需要考虑应用场景
出现频率特别低的词汇对分析作用不大,所以一般也会去掉。把停用词、出现频率低的过滤掉。
五、Stemming (单词转换)
意思相似,合并为同一单词
went,go,going
fly,flies
fast,faster,fastest
stemming 算法合并
from nltk.stem.porter import PorterStemmer
stemmer = PorterStemmer()
test_strs = ['caresses','dies','flies','mules','denied',
'died','agreed','owned','humbled','sized','meeting','stating']
singles = [stemmer.stem(word) for word in test_strs]
print(' '.join(singles))
六、文本表示
单词的表示:最常用的表示方式:词袋模型(Bag-of-words Model)
假设一个词典有7个单词:[我们,去,爬山,今天,你们,昨天,运动]
每个单词的表示:特点- 维度等同于词典的大小,Sparse Vector(只有一个1,其它全是0)
我们:[1,0,0,0,0,0,0]
爬山:[0,0,1,0,0,0,0]
运动:[0,0,0,0,0,0,1]
昨天:[0,0,0,0,0,1,0]
词袋模型(词典维度)
句子的表示方式:
corpus = [
'He is going from Beijing to Shanghai.',
'He denied my request, but he actually lied.',
'Mike lost the phone, and phone was in the car.',
]
[[0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 0 1 0 1 0]
[1 0 0 1 0 1 0 0 2 0 0 1 0 0 1 0 1 0 0 0 0]
[0 1 0 0 1 0 0 0 0 1 0 0 1 1 0 2 0 0 2 0 1]]
tf-idf 表达方式
tf-idf(w) = tf(d,w) * idf(w)
"""文本转化向量"""
corpus = [
'He is going from Beijing to Shanghai.',
'He denied my request, but he actually lied.',
'Mike lost the phone, and phone was in the car.',
]
# 方法1: 只考虑词频
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print(X)
print(x.toArray())
# 方法2: 既考虑词频,也考虑词的重要性(tf-idf)
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toArray())
计算句子相关性? 方法:d = (s1*s2)/|s1|*|s2|(余弦相似度)
我们:[0.1,0.2,0.4,0.2]
爬山:[0.2,0.3,0.7,0.1]
运动:[0.2,0.3,0.6,0.2]
昨天:[0.5,0.9,0.1,0.3]
分布式表示(优点:1、维度小 2、每个位置都是具有一定意义的浮点非0的数)
dist(我们,爬山) = sqrt(0.12)
dist(爬山,运动) = sqrt(0.02)
因此,爬山和运动的相似度高于我们和爬山
分布式表示依赖深度学习模型(word2vec模型 i,e.SkipGram)
句子向量:我们| 昨天|爬山 = () 方法:1、每个维度平均 2、时序(LSTM,RNN)