影视剧字幕聊天语料库特点,把影视剧说话内容一句一句以回车换行罗列三千多万条中国话,相邻第二句很可能是第一句最好回答。一个问句有很多种回答,可以根据相关程度以及历史聊天记录所有回答排序,找到最优,是一个搜索排序过程。

lucene+ik。lucene开源免费搜索引擎库,java语言开发。ik IKAnalyzer,开源中文切词工具。语料库切词建索引,文本搜索做文本相关性检索,把下一句取出作答案候选集,答案排序,问题分析。

建索引。eclipse创建maven工程,maven自动生成pom.xml文件,配置包依赖信息,dependencies标签中添加依赖:

<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>4.10.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>4.10.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>4.10.4</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>

project标签增加配置,依赖jar包自动拷贝lib目录:

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>theMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>

https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/ik-analyzer/IK%20Analyzer%202012FF_hf1_source.rar 下载ik源代码把src/org目录拷到chatbotv1工程src/main/java下,刷新maven工程。

com.shareditor.chatbotv1包下maven自动生成App.java,改成Indexer.java:

Analyzer analyzer = new IKAnalyzer(true);
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_9, analyzer);
iwc.setOpenMode(OpenMode.CREATE);
iwc.setUseCompoundFile(true);
IndexWriter indexWriter = new IndexWriter(FSDirectory.open(new File(indexPath)), iwc);

BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(corpusPath), "UTF-8"));
String line = "";
String last = "";
long lineNum = 0;
while ((line = br.readLine()) != null) {
line = line.trim();

if (0 == line.length()) {
continue;
}

if (!last.equals("")) {
Document doc = new Document();
doc.add(new TextField("question", last, Store.YES));
doc.add(new StoredField("answer", line));
indexWriter.addDocument(doc);
}
last = line;
lineNum++;
if (lineNum % 100000 == 0) {
System.out.println("add doc " + lineNum);
}
}
br.close();

indexWriter.forceMerge(1);
indexWriter.close();

编译拷贝src/main/resources所有文件到target目录,target目录执行

java -cp $CLASSPATH:./lib/:./chatbotv1-0.0.1-SNAPSHOT.jar com.shareditor.chatbotv1.Indexer ../../subtitle/raw_subtitles/subtitle.corpus ./index

生成索引目录index通过lukeall-4.9.0.jar查看。

检索服务。netty创建http服务server,代码在https://github.com/warmheartli/ChatBotCourse的chatbotv1目录:

Analyzer analyzer = new IKAnalyzer(true);
QueryParser qp = new QueryParser(Version.LUCENE_4_9, "question", analyzer);
if (topDocs.totalHits == 0) {
qp.setDefaultOperator(Operator.AND);
query = qp.parse(q);
System.out.println(query.toString());
indexSearcher.search(query, collector);
topDocs = collector.topDocs();
}

if (topDocs.totalHits == 0) {
qp.setDefaultOperator(Operator.OR);
query = qp.parse(q);
System.out.println(query.toString());
indexSearcher.search(query, collector);
topDocs = collector.topDocs();
}

ret.put("total", topDocs.totalHits);
ret.put("q", q);
JSONArray result = new JSONArray();
for (ScoreDoc d : topDocs.scoreDocs) {
Document doc = indexSearcher.doc(d.doc);
String question = doc.get("question");
String answer = doc.get("answer");
JSONObject item = new JSONObject();
item.put("question", question);
item.put("answer", answer);
item.put("score", d.score);
item.put("doc", d.doc);
result.add(item);
}
ret.put("result", result);

查询索引,query词做切词拼lucene query,检索索引question字段,匹配返回answer字段值作候选集,挑出候选集一条作答案。server通过http访问,如http://127.0.0.1:8765/?q=hello 。中文需转urlcode发送,java端读取按urlcode解析,server启动方法:

java -cp $CLASSPATH:./lib/:./chatbotv1-0.0.1-SNAPSHOT.jar com.shareditor.chatbotv1.Searcher

聊天界面。一个展示聊天内容框框,选择ckeditor,支持html格式内容展示,一个输入框和发送按钮,html代码:

<div class="col-sm-4 col-xs-10">
<div class="row">
<textarea id="chatarea">
<div style='color: blue; text-align: left; padding: 5px;'>机器人: 喂,大哥您好,您终于肯跟我聊天了,来侃侃呗,我来者不拒!</div>
<div style='color: blue; text-align: left; padding: 5px;'>机器人: 啥?你问我怎么这么聪明会聊天?因为我刚刚吃了一堆影视剧字幕!</div>
</textarea>
</div>
<br />

<div class="row">
<div class="input-group">
<input type="text" id="input" class="form-control" autofocus="autofocus" onkeydown="submitByEnter()" />
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="submit()">发送</button>
</span>
</div>
</div>
</div>

<script type="text/javascript">

CKEDITOR.replace('chatarea',
{
readOnly: true,
toolbar: ['Source'],
height: 500,
removePlugins: 'elementspath',
resize_enabled: false,
allowedContent: true
});

</script>

调用聊天server,要一个发送请求获取结果控制器:

public function queryAction(Request $request)
{
$q = $request->get('input');
$opts = array(
'http'=>array(
'method'=>"GET",
'timeout'=>60,
)
);
$context = stream_context_create($opts);
$clientIp = $request->getClientIp();
$response = file_get_contents('http://127.0.0.1:8765/?q=' . urlencode($q) . '&clientIp=' . $clientIp, false, $context);
$res = json_decode($response, true);
$total = $res['total'];
$result = '';
if ($total > 0) {
$result = $res['result'][0]['answer'];
}
return new Response($result);
}

控制器路由配置:

chatbot_query:
path: /chatbot/query
defaults: { _controller: AppBundle:ChatBot:query }

聊天server响应时间比较长,不导致web界面卡住,执行submit时异步发请求和收结果:

var xmlHttp;
function submit() {
if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
var input = $("#input").val().trim();
if (input == '') {
jQuery('#input').val('');
return;
}
addText(input, false);
jQuery('#input').val('');
var datastr = "input=" + input;
datastr = encodeURI(datastr);
var url = "/chatbot/query";
xmlHttp.open("POST", url, true);
xmlHttp.onreadystatechange = callback;
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.send(datastr);
}

function callback() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var responseText = xmlHttp.responseText;
addText(responseText, true);
}
}

addText往ckeditor添加一段文本:

function addText(text, is_response) {
var oldText = CKEDITOR.instances.chatarea.getData();
var prefix = '';
if (is_response) {
prefix = "<div style='color: blue; text-align: left; padding: 5px;'>机器人: "
} else {
prefix = "<div style='color: darkgreen; text-align: right; padding: 5px;'>我: "
}
CKEDITOR.instances.chatarea.setData(oldText + "" + prefix + text + "</div>");
}

代码:
https://github.com/warmheartli/ChatBotCourse
https://github.com/warmheartli/shareditor.com

效果演示:http://www.shareditor.com/chatbot/

导流。统计网站流量情况。cnzz统计看最近半个月受访页面流量情况,用户访问集中页面。增加图库动态按钮。吸引用户点击,在每个页面右下角放置动态小图标,页面滚动它不动,用户点了直接跳到想要引流的页面。搜客服漂浮代码。
创建js文件,lrtk.js :

$(function()
{
var tophtml="<a href=\"http://www.shareditor.com/chatbot/\" target=\"_blank\"><div id=\"izl_rmenu\" class=\"izl-rmenu\"><div class=\"btn btn-phone\"></div><div class=\"btn btn-top\"></div></div></a>";
$("#top").html(tophtml);
$("#izl_rmenu").each(function()
{
$(this).find(".btn-phone").mouseenter(function()
{
$(this).find(".phone").fadeIn("fast");
});
$(this).find(".btn-phone").mouseleave(function()
{
$(this).find(".phone").fadeOut("fast");
});
$(this).find(".btn-top").click(function()
{
$("html, body").animate({
"scroll-top":0
},"fast");
});
});
var lastRmenuStatus=false;

$(window).scroll(function()
{
var _top=$(window).scrollTop();
if(_top>=0)
{
$("#izl_rmenu").data("expanded",true);
}
else
{
$("#izl_rmenu").data("expanded",false);
}
if($("#izl_rmenu").data("expanded")!=lastRmenuStatus)
{
lastRmenuStatus=$("#izl_rmenu").data("expanded");
if(lastRmenuStatus)
{
$("#izl_rmenu .btn-top").slideDown();
}
else
{
$("#izl_rmenu .btn-top").slideUp();
}
}
});
});

上半部分定义id=top的div标签内容。一个id为izl_rmenu的div,css格式定义在另一个文件lrtk.css里:

.izl-rmenu{position:fixed;left:85%;bottom:10px;padding-bottom:73px;z-index:999;}
.izl-rmenu .btn{width:72px;height:73px;margin-bottom:1px;cursor:pointer;position:relative;}
.izl-rmenu .btn-top{background:url(http://www.shareditor.com/uploads/media/default/0001/01/thumb_416_default_big.png) 0px 0px no-repeat;background-size: 70px 70px;display:none;}

下半部分当页面滚动时div展开。

在所有页面公共代码部分增加

<div id="top"></div>

庞大语料库运用,LSTM-RNN训练,中文语料转成算法识别向量形式,最强大word embedding工具word2vec。

word2vec输入切词文本文件,影视剧字幕语料库回车换行分隔完整句子,所以我们先对其做切词,word_segment.py文件:

# coding:utf-8

import sys
import importlib
importlib.reload(sys)

import jieba
from jieba import analyse

def segment(input, output):
input_file = open(input, "r")
output_file = open(output, "w")
while True:
line = input_file.readline()
if line:
line = line.strip()
seg_list = jieba.cut(line)
segments = ""
for str in seg_list:
segments = segments + " " + str
segments = segments + "\n"
output_file.write(segments)
else:
break
input_file.close()
output_file.close()

if __name__ == '__main__':
if 3 != len(sys.argv):
print("Usage: ", sys.argv[0], "input output")
sys.exit(-1)
segment(sys.argv[1], sys.argv[2]);

使用:

python word_segment.py subtitle/raw_subtitles/subtitle.corpus segment_result

word2vec生成词向量。word2vec可从https://github.com/warmheartli/ChatBotCourse/tree/master/word2vec获取,make编译生成二进制文件。
执行:

./word2vec -train ../segment_result -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 1 -iter 15

生成vectors.bin词向量,二进制格式,word2vec自带distance工具来验证:

./distance vectors.bin

词向量二进制文件格式加载。word2vec生成词向量二进制格式:词数目(空格)向量维度。
加载词向量二进制文件python脚本:

# coding:utf-8

import sys
import struct
import math
import numpy as np

reload(sys)
sys.setdefaultencoding( "utf-8" )

max_w = 50
float_size = 4

def load_vectors(input):
print "begin load vectors"

input_file = open(input, "rb")

# 获取词表数目及向量维度
words_and_size = input_file.readline()
words_and_size = words_and_size.strip()
words = long(words_and_size.split(' ')[0])
size = long(words_and_size.split(' ')[1])
print "words =", words
print "size =", size

word_vector = {}

for b in range(0, words):
a = 0
word = ''
# 读取一个词
while True:
c = input_file.read(1)
word = word + c
if False == c or c == ' ':
break
if a < max_w and c != '\n':
a = a + 1
word = word.strip()

# 读取词向量
vector = np.empty([200])
for index in range(0, size):
m = input_file.read(float_size)
(weight,) = struct.unpack('f', m)
vector[index] = weight

# 将词及其对应的向量存到dict中
word_vector[word.decode('utf-8')] = vector

input_file.close()

print "load vectors finish"
return word_vector

if __name__ == '__main__':
if 2 != len(sys.argv):
print "Usage: ", sys.argv[0], "vectors.bin"
sys.exit(-1)
d = load_vectors(sys.argv[1])
print d[u'真的']

运行方式如下:

python word_vectors_loader.py vectors.bin

参考资料:

《Python 自然语言处理》

http://www.shareditor.com/blogshow?blogId=113

http://www.shareditor.com/blogshow?blogId=114

http://www.shareditor.com/blogshow?blogId=115

欢迎推荐上海机器学习工作机会,我的微信:qingxingfengzi

学习笔记CB011:lucene搜索引擎库、IKAnalyzer中文切词工具、检索服务、查询索引、导流、word2vec的更多相关文章

  1. Solr学习笔记之2、集成IK中文分词器

    Solr学习笔记之2.集成IK中文分词器 一.下载IK中文分词器 IK中文分词器 此文IK版本:IK Analyer 2012-FF hotfix 1 完整分发包 二.在Solr中集成IK中文分词器 ...

  2. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  3. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...

  4. openresty 学习笔记六:使用session库

    openresty 学习笔记六:使用session库 lua-resty-session 是一个面向 OpenResty 的安全和灵活的 session 库,它实现了 Secure Cookie Pr ...

  5. mongoDB 学习笔记纯干货(mongoose、增删改查、聚合、索引、连接、备份与恢复、监控等等)

    最后更新时间:2017-07-13 11:10:49 原始文章链接:http://www.lovebxm.com/2017/07/13/mongodb_primer/ MongoDB - 简介 官网: ...

  6. Java实现敏感词过滤 - IKAnalyzer中文分词工具

    IKAnalyzer 是一个开源的,基于java语言开发的轻量级的中文分词工具包. 官网: https://code.google.com/archive/p/ik-analyzer/ 本用例借助 I ...

  7. .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]

    原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...

  8. 【转】mongoDB 学习笔记纯干货(mongoose、增删改查、聚合、索引、连接、备份与恢复、监控等等)

    mongoDB 学习笔记纯干货(mongoose.增删改查.聚合.索引.连接.备份与恢复.监控等等) http://www.cnblogs.com/bxm0927/p/7159556.html

  9. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引 代码工程地址: https://g ...

随机推荐

  1. C#Mvc批量删除

    前台页面(JQuery) @*全选&批删*@<script type="text/javascript"> $(document).ready(function ...

  2. sass学习笔记(一)接上个 持续学习中..(还发现个讲解的bug) sass至少我现在学的版本支持局部变量了

    6.全局变量 sass暂时没有局部变量 局部定义变量会覆盖全局变量 新出!global 不过要sass 3.4版本以后        (这句呢,,我觉得是错的 开始写的时候没测试 现在发现我觉得他是有 ...

  3. 《JavaScript Dom 编程艺术》读书笔记-第10章

    用JS实现动画~内容包括: 1. 动画基础知识 2. 用动画丰富网页的浏览效果 动画就是让元素的位置随时间而不断变化. 位置: //CSSelement{ position:absolute; top ...

  4. effective java——32用EnumSet代替位域

    什么是位域?为什么用到它?先来看一个例子: public class Test { public static final byte STYLE_BOLD = 1<<0; // 1 pub ...

  5. L360 Most People Spend Their Time in Just 25 Places

    Some people are always out on the town, going to concerts, restaurant openings, you name it. They're ...

  6. Python第八章(北理国家精品课 嵩天等)

    程序设计方法 8.1体育竞技分析实例 from random import random def printIntro(): print("这个程序模拟两个选手A和B的某种竞技比赛" ...

  7. 关于JDBC和连接池我学到的(转载保存)

    1.JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接. 进行sql操作 断开数据库连接. 这种模 ...

  8. 'touch' 不是内部或外部命令,也不是可运行的程序或批处理文件。

    touch是Linux环境下的命令,当我们在cmd中使用时会弹出以下问题 在cmd中我们可以使用echo test> 然后我们用dir命令来查看一下当前文件夹下文件有没有创建 文件成功创建.

  9. 周强 201771010141 《面向对象程序设计(java)》第九周实验总结

    实验部分 1.实验目的与要求 (1) 掌握java异常处理技术: (2) 了解断言的用法: (3) 了解日志的用途: (4) 掌握程序基础调试技巧: 2.实验内容和步骤 实验1:用命令行与IDE两种环 ...

  10. vue2.0 + element-ui 通过vue-cli 脚手架搭建的有关网络安全的项目源代码

    这次是我进入公司的练手项目,是第一次系统学习vue,做出来的demo是比较低端的,而且不太好看,见谅见谅. 源代码下载路径:https://github.com/Pandora-ps/vue-elem ...