美文网首页机器学习与数据挖掘
一个简易版的智能搜索系统(上)

一个简易版的智能搜索系统(上)

作者: dc343001cf91 | 来源:发表于2018-07-25 16:32 被阅读30次

一个简易的智能搜索引擎

        在公司工作的过程中,我构建了一个简易的智能搜索系统,具体功能可以进入杭州质量服务网进行查看,这个流程主要是通过R语言和Python进行实现的。接下来我会逐步介绍如何实现这个搜索系统。

1. 数据存储结构和形式

        杭州质量网的标准查询数据存在我们服务器上,以下是我所使用到的数据案例,对于标准查询,领导交给我们的要求是标题匹配,这里我就没有取出正文进行计算。release_date这个变量是为了进行时间加权,领导表示不想看到几十年前的标准。

id chinese_title english_title release_date
659758 制药机械(设备)清洗、灭菌验证导则 Verify guidance of cleaning and sterilization for pharmaceutical machinery 2018/3/15
659638 数字印刷系统的使用要求及检验方法 Use requirements and test methods for digital printing system 2018/3/15
659523 浮法玻璃拉边机 Top roller of float glass 2018/3/15
659430 流体输送用热塑性塑料管道系统 耐内压性能的测定 Thermoplastics piping systems for the conveyance of fluids—Determination of the resistance to internal pressure 2018/3/15
659399 家具中重金属锑、砷、钡、硒、六价铬的评定方法 The assessment method of the heavy metal Sb,As,Ba,Se and Cr(Ⅵ)in furniture 2018/3/15
659398 纺织品 非织造布试验方法 第15部分:透气性的测定 Textiles—Test methods for nonwovens—Part 15: Determination of air permeability 2018/3/15
659403 纺织品 机织物接缝处纱线抗滑移的测定 第2部分:定负荷法 Textiles—Determination of the slippage resistance of yarns at seam in woven fabric—Part 2: Fixed load method 2018/3/15
659397 纺织品 生理舒适性 稳态条件下热阻和湿阻的测定(蒸发热板法) Textiles-Physiological effects-Measurement of thermal and water-vapour resistance under steady-state conditions(sweating guarded-hotplate test) 2018/3/15
659395 木家具中氨释放量试验方法 Test methods of ammonia emission of wooden furniture 2018/3/15
659406 集成电路倒装焊试验方法 Test methods for flip chip integrated circuits 2018/3/15

2. 如何计算定义搜索相关度

        搜索引擎以前最常用的一个数学模型就是TF_IDF,我这里也是套用了这个模型。不过由于领导们的小需求--hh领导要求我们搜索番茄的同时要搜索西红柿,也就是实现同义搜索,也可以说是联想搜素。因此我将用户的输入先进行一个关键词的联想,具体的实现手段放在后面讲解,这部分我先介绍最简单的TF_IDF值的计算,由于这部分内容是刚毕业的时候做的。当时只会R不会python的优化,对几千万篇文章进行处理我的代码运行效率实在太低,所以果断放弃了python。

2.1 从数据库中导入数据

rm(list = ls())                             # 清洗变量空间
setwd("D:/www/ElasticSearch/fencimoxing")   # 设定工作路径
library(RMySQL)                             # 数据库操作的一个包
con <- dbConnect(MySQL(),
                 host='**.***.**.**',       # ip地址
                 port=****,                 # 端口号
                 dbname="********",         # 数据库名字
                 user="****",               # 数据库的用户名
                 password="*****")          # 数据库的密码
dbSendQuery(con, 'SET NAMES gbk')           # 设定gbk编码,不然中文会乱码
# 从数据库中选取id,chinese_title,english_title,release_date
data <- dbGetQuery(con, "SELECT id, chinese_title, english_title, release_date FROM nqi_std") 
data$text <- paste(data$chinese_title, data$english_title)

2.2 日期转数值

        当数据读入到我们的变量空间的时候我们要考虑2件事情一个是时间变量的处理,还有一个是文本的分词。时间变量的处理我打算是直接对数据进行个转换,将其变成一个[1-2]的数,距离现在越近数值越大。

library(data.table)                         # 导入data.table包 R语言多线程数据清洗包
nqi_std <- data.table(data)                 # 转换为data.table
# 删除"chinese_title", "english_title"2列
nqi_std <- nqi_std[, c("chinese_title", "english_title") := NULL] 
# 提取日期数据并进行升序排序,缺失值和日期较小的值会默认在前面sort函数是这样子的
release_date <- sort(unique(nqi_std[, release_date]))
# seq(...)这里是产生了等间隔的数值,分布为1-2
date_to_num <- data.table(cbind(release_date, 
                                dateweight = seq(from = 1+1/length(release_date), to = 2, by = 1/length(release_date))))
setkey(date_to_num, release_date)           # 设定主键release_date
setkey(nqi_std, release_date)               # 设定主键release_date
nqi_std <- merge(nqi_std, date_to_num)      # 主键相同的表才可以合并
nqi_std <- nqi_std[, release_date := NULL]  # 日期数据已经没用了可以直接去除
# 由于r语言cbind后产生的是是矩阵,要求的数据类型为一样,故dateweight变成了一堆字符串,这里需要进行转换
nqi_std <- nqi_std[, dateweight := as.numeric(nqi_std[, dateweight])]

2.3 定义一个分词器

        由于某某领导的病态要求:我们这个一定要好好弄像什么凡尔滨对虾啊,秋叶葵啊,这些正常人都不知道的名词也要好好地给我分词分出来。没办法啊,我们只能去把整个搜狗细胞词库拉下来,然后整理了接近5000万条的词库。包含了“腓骨钢板钛合金”,“肺吸虫抗体检测试剂”等等这样的词语,终于基本满足了领导的病态需求。搜狗细胞词库的转换代码我是参考的qinwf开发的cidian包,请移步其个人主页查看具体实现原理。注意这个包不能再64位R上运行和安装,请用32位的运行。

library(jiebaR)
cutquery <- worker(type = "query",          # 定义切词模式,我经过多次尝试,觉得这种最合适
                   user = "dict.txt",       # 个人词库
                   stop_word = "stop.txt",  # 停止词词库
                   encoding = "UTF-8")      # 文件编码
# 分词函数
fenci <- function(x){
  # 将文字中的空白字符,数字,标点符号都替换为空格,替换为空格就是变成分隔符,
  x <- gsub("[[:space:]]|[[:punct:]]|[[:digit:]]", " ", x) 
  # 进行分词
  cut_result <- segment(tolower(x), cutquery)
  return(cut_result)
}

2.4 分词并计算TF_IDF值

        直接进行TF_IDF值的计算并用权重加权。

# 保留id和dateweight属性下进行分词
nqi_std <- nqi_std[, lapply(.SD, fenci), by = .(id, dateweight)]
nqi_std[, count2 := .N, by = id]            # 计算每个标准的词语数量
nqi_std[, count3 := .N, by = .(id, text)]   # 计算每个词语在当前文档中的出现数量
nqi_std <- unique(nqi_std)                  # 去重后才能计算词语在所有文档中出现的文档个数
nqi_std[, count1 := .N, by = text]          # 计算词语在所有文档中出现的文档个数
papercount <- nrow(data)                    # 计算文档个数
nqi_std[, TF_IDF := count3/count2 * log(papercount/(count1+1) * dateweight)]
# TF = count3/count2, IDF = log(papercount/(count1+1)

2.5 分词结果导出

        将所有的分词结果按词语名导出到某个固定文件夹路径下。

setkey(nqi_std, text)                   # 设定text主键,方便后续操作
mykeyword <- unique(nqi_std[,text])     # 关键词去重
Encoding(mykeyword) <- "UTF-8"          # 设置编码,否则无法写出中文文件
setwd("D:/www/ElasticSearch/wordscore") # 设定工作路径
lf <- list.files(".", pattern = "txt")  # 查看所有txt文件
file.remove(lf)                         # 删除原有文件
# 写入文件函数
writedata <- function(x){
  file <- paste(x, ".txt", sep = "")    # 设定新产生的文件名
  result <- nqi_std[list(x)]            # 筛选符合条件的数据
  write.table(result[, text := NULL], file, quote = FALSE, row.names = FALSE, fileEncoding = "UTF-8",sep = "\t")  
}
# 写入文件
lapply(mykeyword, writedata)
rm(list=ls())                           # 释放内存

源代码请移步Githubhttps://github.com/wujialin123/hzzlw_Standardsearch

相关文章

网友评论

    本文标题:一个简易版的智能搜索系统(上)

    本文链接:https://www.haomeiwen.com/subject/oadjmftx.html