感觉大佬的代码写的就是好,在处理数据的方面,首先定义一个 提取特征的类, class Extractor(object):,然后每一种方法对这个类进行重构,这个类主要结构就是:

class Extractor(object):
def __init__(self, config_fp):
# set feature name
self.feature_name = self.__class__.__name__
# set feature file path
self.data_feature_fp = None
# load configuration file
self.config = configparser.ConfigParser()
self.config.read(config_fp) # 这个函数什么都没写,就是用来重构的,表示特征的个数
def get_feature_num(self):
assert False, 'Please override function: Extractor.get_feature_num()'
# assert False 后面加字符串就是为了解释哪里出错的,给出错误信息 def extract_row(self, row):
assert False, 'Please override function: Extractor.extract_row()' # 抽取原始数据的特征
def extract(self, data_set_name, part_num=1, part_id=0):
"""
Extract the feature from original data set
:param data_set_name: name of data set
:param part_num: number of partitions of data
:param part_id: partition ID which will be extracted
:return:
"""

接下来看如何具体的从统计的角度与 NLP 的角度处理数据

统计学的角度处理数据的方法

从统计学的角度考虑主要是单词的频率,数据的次数等等,这里考虑的问题很多,总结来说就是,每种方法的处理套路是,使用分词,然后使用词干提取的方法,将所有的单词进行词干归一化处理。注意,这里是从统计的角度考虑问题,那么就不要考虑到单词的时态问题,词干提取可以更好的表示出现的频率。

主要使用的方法总结,之后我会具体说一下使用的比较复杂的方法:

  1. Not 类,统计一句话中 ‘not’ 出现的次数
  2. WordMatchShare 类,两句话中均出现的单词的占所有单词的比例
  3. TFIDFWordMatchShare 类,与前面的类似,只不过这里加权了文件的出现次数
  4. Length 类,表示长度的一些数据
  5. LengthDiff 类表示问题的长度之差
  6. LengthDiffRate 类,数据上比较长短
  7. PowerfulWord 这个类是为后面服务的,计算数据中词语的影响力
  8. PowerfulWordOneSide 类,考虑单词出现的比例以及正确的比例
  9. PowerfulWordDoubleSideRate 类,考虑两边都出现的单词的比例,以及这些单词对应的 label 的比例
  10. TFIDF 类,使用 sklearn 中方法直接获取 TFIDF 类
  11. DulNum 类,计算完全重复的问题的数量
  12. EnCharCount 类,统计每句话中字母的出现的频率,
  13. NgramJaccardCoef 类,使用 ngram 的方法计算两个问题之间的距离
  14. NgramDiceDistance 类,与上面的方法类似,只是计算距离的方法不同
  15. Distance 类,这里是下面的方法父类,是用于计算句子之间距离的工具
  16. NgramDistance 类,这个主要是在上面的基础上,结合矩阵的距离的方法
  17. InterrogativeWords 类,这个主要是统计疑问句的比例

TFIDFWordMatchShare 方法

TFIDFWordMatchShare 这个方法是考虑单词出现在文件的次数,也就是 IDF 的意思,然后用这个加权来表示共同出现的单词的加权的文件的比例,这里具体看下重点的代码就是:

def init_idf(data):
idf = {}
# 先统计了单词的 IDF 值
num_docs = len(data)
for word in idf:
idf[word] = math.log(num_docs / (idf[word] + 1.)) / math.log(2.)
# 这里是一个对数中的换底公式
LogUtil.log("INFO", "idf calculation done, len(idf)=%d" % len(idf))
# 返回一个字典,是整个文件中的单词的,平均每个单词出现在文件中的次数,
# 比如说,5个文件,这个单词一共出现了三次,那么就是 5/3
return idf def extract_row(self, row):
qwords = {}
# 这里是先统计了单词出现的次数, qword来计算,
# 下面的这个公式计算的是, 同时出现在两个问题中的单词他们所加权的文件总数
# 比如说,上面前面计算 IDF 是对于整个文件来说,单词 'word'的idf值是 5/3,那么对于这一句话来说,'word' 出现了两次,并且 # 'word' 在两个问题均出现,那么这个值就是 10 /3 ,然后对于每个出现的单词计算就可以了
sum_shared_word_in_q1 = sum([q1words[w] * self.idf.get(w, 0) for w in q1words if w in q2words])
sum_shared_word_in_q2 = sum([q2words[w] * self.idf.get(w, 0) for w in q2words if w in q1words])
sum_tol = sum(q1words[w] * self.idf.get(w, 0) for w in q1words) + sum(
q2words[w] * self.idf.get(w, 0) for w in q2words)
if 1e-6 > sum_tol:
return [0.]
else:
return [1.0 * (sum_shared_word_in_q1 + sum_shared_word_in_q2) / sum_tol]

PowerfulWord 方法

这个方法是统计单词的权重及比例,

def generate_powerful_word(data, subset_indexs):
"""
计算数据中词语的影响力,格式如下:
词语 --> [0. 出现语句对数量,1. 出现语句对比例,2. 正确语句对比例,3. 单侧语句对比例,4. 单侧语句对正确比例,
5. 双侧语句对比例,6. 双侧语句对正确比例]
"""
words_power = {}
train_subset_data = data.iloc[subset_indexs, :]
# 取出 subset_indexs中的所有的行
# 然后遍历 subset_indexs 中的所有的行 class PowerfulWordDoubleSide(Extractor):
# 通过设置阈值来提取这句话中关键的单词,然后组成单词向量
def init_powerful_word_dside(pword, thresh_num, thresh_rate):
pword_dside = []
# 出现语句对的数量乘以双侧语句对的比例,得到双侧语句对的数量,
# 计算两边都出现,并且比例高的单词,然后从大到小排序
pword = filter(lambda x: x[1][0] * x[1][5] >= thresh_num, pword)
# 抽取出 pword 中满足条件的所有项目
pword_sort = sorted(pword, key=lambda d: d[1][6], reverse=True)
# 表示按照降序排序
pword_dside.extend(map(lambda x: x[0], filter(lambda x: x[1][6] >= thresh_rate, pword_sort)))
# 在list的结尾追加一序列的值
LogUtil.log('INFO', 'Double side power words(%d): %s' % (len(pword_dside), str(pword_dside)))
return pword_dside

句子之间的距离的计算

由于之前自己对句子之间的距离的了解也比较少,所以这里写的详细一点,这里的主要思想是

class Distance(Extractor):

    def __init__(self, config_fp, distance_mode):
Extractor.__init__(self, config_fp)
self.feature_name += '_%s' % distance_mode
self.valid_distance_mode = ['edit_dist', 'compression_dist']
# 这两个方法是计算两个字符串之间的距离使用的,其中 'edit_dist' 直接调用的一个方法,而'compression_dist'通过简单计算
# 就可以得到
assert distance_mode in self.valid_distance_mode, "Wrong aggregation_mode: %s" % distance_mode
# 初始化参数
self.distance_mode = distance_mode
# 使用不同的方法来计算字符串之间的距离
self.distance_func = getattr(DistanceUtil, self.distance_mode) def extract_row(self, row):
q1 = str(row['question1']).strip()
q2 = str(row['question2']).strip()
q1_stem = ' '.join([snowball_stemmer.stem(word).encode('utf-8') for word in
nltk.word_tokenize(TextPreProcessor.clean_text(str(row['question1']).decode('utf-8')))])
q2_stem = ' '.join([snowball_stemmer.stem(word).encode('utf-8') for word in
nltk.word_tokenize(TextPreProcessor.clean_text(str(row['question2']).decode('utf-8')))])
# 先分词,然后将单词用空格连成句子,假装是句子
return [self.distance_func(q1, q2), self.distance_func(q1_stem, q2_stem)] def get_feature_num(self):
return 2 class NgramDistance(Distance):
# 这里没有构造函数,子类直接调用父类的构造函数
def extract_row(self, row):
# 使用词干提取
fs = list()
aggregation_modes_outer = ["mean", "max", "min", "median"]
aggregation_modes_inner = ["mean", "std", "max", "min", "median"]
# 这些主要是 np 中矩阵的一些方法,用于数据处理均值,最大值,最小值,中位数,矩阵的标准差 等等
for n_ngram in range(1, 4):
q1_ngrams = NgramUtil.ngrams(q1_words, n_ngram)
q2_ngrams = NgramUtil.ngrams(q2_words, n_ngram) val_list = list()
for w1 in q1_ngrams:
_val_list = list()
for w2 in q2_ngrams:
s = self.distance_func(w1, w2)
# 两个句子在 ngram 下面的距离,然后存起来
_val_list.append(s)
if len(_val_list) == 0:
_val_list = [MISSING_VALUE_NUMERIC]
val_list.append(_val_list)
if len(val_list) == 0:
val_list = [[MISSING_VALUE_NUMERIC]]
# val_list 存的就是在 q1_ngrams 下每两个句子之间的距离,组成一个矩阵
for mode_inner in aggregation_modes_inner:
tmp = list()
for l in val_list:
tmp.append(MathUtil.aggregate(l, mode_inner))
fs.extend(MathUtil.aggregate(tmp, aggregation_modes_outer))
return fs def get_feature_num(self):
return 4 * 5

NLP 角度处理数据的方法

这里主要考虑的是解析树的构成,构建一颗解析树,从语句的解析树提取句子的特征,

def init_tree_properties(tree_fp):
features = {}
f = open(tree_fp)
for line in f:
[qid, json_s] = line.split(' ', 1)
# 分割一次,分成两个
features[qid] = []
root = -1
parent = {}
indegree = {}
# calculate in-degree and find father
# 删除开头与结尾的空格
if 0 < len(json_s.strip()):
tree_obj = json.loads(json_s)
# 将一个JSON编码的字符串转换回一个Python数据结构:
# 返回一个字典
assert len(tree_obj) <= 1
tree_obj = tree_obj[0]
for k, r in sorted(tree_obj.items(), key=lambda x: int(x[0]))[1:]:
if r['word'] is None:
continue
head = int(r['head'])
k = int(k)
if 0 == head:
root = k
parent[k] = head
indegree[head] = indegree.get(head, 0) + 1
# calculate number of leaves
n_child = 0
for i in parent:
if i not in indegree:
n_child += 1
# calculate the depth of a tree
depth = 0
for i in parent:
if i not in indegree:
temp_id = i
temp_depth = 0
while (temp_id in parent) and (0 != parent[temp_id]):
temp_depth += 1
temp_id = parent[temp_id]
depth = max(depth, temp_depth)
# calculate the in-degree of root
n_root_braches = indegree.get(root, 0)
# calculate the max in-degree
n_max_braches = 0
if 0 < len(indegree):
n_max_braches = max(indegree.values())
features[str(qid)] = [n_child, depth, n_root_braches, n_max_braches]
f.close()
return features

分析 Kaggle TOP0.1% 如何处理文本数据的更多相关文章

  1. J2EE综合:如何处理大数据量的查询

    在实际的任何一个系统中,查询都是必不可少的一个功能,而查询设计的好坏又影响到系统的响应时间和性能这两个要害指标,尤其是当数据量变得越来越大时,于是如何处理大数据量的查询成了每个系统架构设计时都必须面对 ...

  2. NLP相关问题中文本数据特征表达初探

    1. NLP问题简介 0x1:NLP问题都包括哪些内涵 人们对真实世界的感知被成为感知世界,而人们用语言表达出自己的感知视为文本数据.那么反过来,NLP,或者更精确地表达为文本挖掘,则是从文本数据出发 ...

  3. scikit-learning教程(三)使用文本数据

    使用文本数据 本指南的目标是探讨scikit-learn 一个实际任务中的一些主要工具:分析二十个不同主题的文本文档(新闻组帖子)集合. 在本节中,我们将看到如何: 加载文件内容和类别 提取适用于机器 ...

  4. Bulk Insert:将文本数据(csv和txt)导入到数据库中

    将文本数据导入到数据库中的方法有很多,将文本格式(csv和txt)导入到SQL Server中,bulk insert是最简单的实现方法 1,bulk insert命令,经过简化如下 BULK INS ...

  5. 业务人员自助BI分析不够用,还要自助数据准备?

    自助式BI工具,可以帮助业务人员充分了解和利用企业数据,通过可视化操作,拖拖拽拽来新建分析,生成可视化的报表,帮助企业决策.但近几年的调查研究发现,拥有强大分析策略和模型的产品,比如Tableau.q ...

  6. JAVASE02-Unit08: 文本数据IO操作 、 异常处理

    Unit08: 文本数据IO操作 . 异常处理 * java.io.ObjectOutputStream * 对象输出流,作用是进行对象序列化 package day08; import java.i ...

  7. JAVASE02-Unit07: 基本IO操作 、 文本数据IO操作

    基本IO操作 . 文本数据IO操作 java标准IO(input/output)操作 package day07; import java.io.FileOutputStream; import ja ...

  8. 《BI那点儿事》SSRS图表和仪表——雷达图分析三国超一流谋士、统帅数据(图文并茂)

    雷达图分析三国超一流谋士.统帅数据,献给广大的三国爱好者们,希望喜欢三国的朋友一起讨论,加深对传奇三国时代的了解 建立数据环境: -- 抽取三国超一流谋士TOP 10数据 DECLARE @t1 TA ...

  9. 10、NFC技术:读写NFC标签中的文本数据

    代码实现过程如下: 读写NFC标签的纯文本数据.java import java.nio.charset.Charset; import java.util.Locale; import androi ...

随机推荐

  1. 《JavaScript高级程序设计》笔记:高级技巧

    高级函数 安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串.每个类在内部都有一个[[Cla ...

  2. Springboot生成二维码并下载图片png支持打包成zip

    pom.xml <!--二维码--> <dependency> <groupId>com.google.zxing</groupId> <arti ...

  3. XenCenter安装VM

    XenServer是服务器"虚拟化系统".系统设置为Linux_x86-64即可安装XenServer 和VMware ESX/ESXi有点不同的是,XenServer 不能在Xe ...

  4. Python 栈、队列的实现

    在python中,列表既可以作为栈使用,又可以作为队列使用. 把列表作为栈使用 栈:后进先出 stack=[1,2,3] stack.append(4) #入栈,以列表尾部为栈顶 print(stac ...

  5. 15 Android系统安全(简要)

    Android的用户和第三方软件,Android组件和数据安全 手机root后的问题:1.系统不稳定,2.病毒入侵,3.数据泄露 Root原理: Root分两类:1.临时root,2.永久root R ...

  6. Nexus安装和使用

    1.前言 最近项目需要搭建maven私服,方便管理后期团队成员使用上传自己的包,因此决定使用nexus来搭建私服,搭建好的nexus地址. 2.准备工作 阿里云服务器ECS一台 1核CPU 2G内存( ...

  7. Kubernetes学习之路(28)之镜像仓库Harbor部署

    Harbor的部署 官方文档 Harbor有两种安装的方式: 在线安装:直接从Docker Hub下载Harbor的镜像,并启动. 离线安装:在官网上下载离线安装包其地址为:https://githu ...

  8. LVS负载均衡部署

    一.lvs-nat模式 1.1.环境介绍 本实验用三台虚拟机完成,一台虚拟机模拟lvs调度器,两块网卡,一块模拟公网一块模拟私网,公网地址192.168.0.201/24,私网地址192.168.4. ...

  9. Go编程基础(介绍和安装)

    Michaelhbjian 2018.10.07 19:41 字数 892 阅读 317评论 0喜欢 0 Go(又称Golang[3])是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回 ...

  10. Beta冲刺(5/7)——2019.5.26

    所属课程 软件工程1916|W(福州大学) 作业要求 Beta冲刺(5/7)--2019.5.26 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪万里 ...