基于知识图谱的问答系统
一.准备工作:
1.下载好java8,并用mysql创建好数据库–重点在于存储数据
2.spark安装–用来进行提问问题的分类算法的编写
3.进行neo4j–用来存储mysql对应的数据库的关系–重点在于存储关系
4.之后在mysql当中将相应数据库当中的表格进行导出为csv文件,便于neo4j图形数据库的读取.将导出的csv文件放在import文件夹当中.
5.安装hanlp中文分词器—这个主要是用来对 所输入的问题进行词语提取,形成一个词向量,之后使用后面会讲到的贝叶斯分类算法,得到该问题在不同问题模版上的匹配概率,取最大的概率,确定为该问题的匹配模版.第三节会讲到.
二.设计贝叶斯分类算法
1.创建进程—(为了后面并行处理分类问题的计算,提高训练速度与测试速度)
2.创建向量–(denseVecto与sparseVector)–稠密向量与稀疏向量
Dense Vector and Sparse Vector。在spark.ml.linalg里有两种vector——DenseVector 和 Sparse Vector,两者都继承于Vectors。
区别:
DenseVector: a value array--(直接把所有的元素都列出来了)`
def: Vectors.dense(values: Array[Double])
SparseVector : an index and a value array--(存储元素的个数、以及非零元素的编号index和值value)
def: Vectors.sparse(size: Int, indices: Array[Int], values: Array[Double])
3,设置标签—使用labelpoint()方法为对应的向量来人为指定标签.
例如:
//训练集生成 ,规定数据结构为LabeledPoint == 构建方式:稠密向量模式 ,1.0:类别编号 == 男性
LabeledPoint train_one = new LabeledPoint(1.0,vMale); //(1.0, 0.0, 1.0, 0.0, 1.0, 0.0)
//训练集生成 ,规定数据结构为LabeledPoint == 构建方式:稀疏向量模式 ,2.0:类别编号 == 女性
LabeledPoint train_two = new LabeledPoint(2.0,vFemale); //(1.0, 1.0, 1.0, 1.0, 0.0, 1.0)
//我们也可以给同一个类别增加多个训练集
LabeledPoint train_three = new LabeledPoint(2.0,Vectors.dense(0,1,1,1,0,1));
创建向量–一般人为创建的向量并且人为指定标签的叫做有标注的训练数据,测试数据一般采用用户输入语句(先创建一个 词向量,之后使用HANLP,分割语句,形成单词,之后在词汇表当中进行查找,根据存在与否对向量里面的元素进行设置0或者1,然后得到一个查找设置后的向量.之后采用贝叶斯方法进行问题模版匹配,来设置标签)
4.用List列表存放训练集—便于后面的数据转换
//List存放训练集【三个训练样本数据】--
List<LabeledPoint> trains = new ArrayList<>();
trains.add(train_one);
trains.add(train_two);
trains.add(train_three);
5.训练数据集的格式转换—-将List训练数据集转换成JAVARDD.就是一个转换成RDD的接口,之后再转换成RDD格式的数据,最终是为了便于spark框架对训练数据集进行并行处理,提高并行速度.
/**
* 利用Spark进行数据分析时,数据一般要转化为RDD
* JavaRDD转Spark的RDD
* SPARK的核心是RDD(弹性分布式数据集)
* Spark是Scala写的,JavaRDD就是Spark为Java写的一套API
*/
JavaRDD<LabeledPoint> trainingRDD = sc.parallelize(trains);
/*
形成一个训练模型
*/
NaiveBayesModel nb_model = NaiveBayes.train(trainingRDD.rdd());
6.之后利用这个训练模型进行测试数据的模型匹配.
double [] dTest = {1,0,1,0,0,0};
Vector vTest = Vectors.dense(dTest);//测试对象为单个vector,或者是RDD化后的vector
//朴素贝叶斯用法
int modelIndex =(int) nb_model.predict(vTest);
System.out.println("标签分类编号:"+modelIndex);// 分类结果 == 返回分类的标签值
三.HANLP分词器的运行流程
具体过程如下:
3.1分割语句,创建词向量—使用HANLP分割出输入语句的各个单词,同时设置一个词向量(用来存储该语句在词汇表当中的情况)
3.2标注词向量内部元素—之后分割出来的词(同时也会标注,也可以人为设定)在词汇表当中进行查找,存在的话使得对应的索引为1,不存在则为0,以此类推,这样就可以得到一个词向量.
3.3提取语句—这个词向量在通过贝叶斯分类算法训练样本数据集得到的训练模型进行测试,就会得到这个词向量与各个问题模版(也就是属于哪一类问题,例如是评分问题,还是演员问题,其实就是以恶搞标签)的匹配概率,取最大的概率,作为该语句(词向量)的问题模版: 例如nm 评分问题—所以这就对问题进行了简化:例如: 英雄这部电影的评分是多少–>nm 这部电影的评分是多少–>通过贝叶斯分类算法得到–>nm 评分–>之后将英雄带回到nm中得到:英雄 评分
3.4然后在neo4j数据库当中进行查找,查找语句: match(n) where n.name=’英雄’ from movie.genre得到最后的答案.—-得到结果
四.NEO4J的语法
结合表达式: match(n)-[r] -(b) 一般都是先进行查找,之后进行操作(通常)
如果查询节点n 就 return n
如果查询关系r 就 return r
如果查询节点b 就 return b
如果查询节点n和b之间的关系r 就 return n,r,b
如果查询带条件 就 where n.x = x,r.xx = xx,b.xxx = xxx
如果修改属性 就 where….. set ….
如果删除属性 就 where….. remove …..
如果删除节点或关系 就 where….. delete n 或者 delete r 或者 delete b 或者 delete n , r , b