0%

NLP = NLU + NLG

  • NLU: 语音/文本 -> 意思
  • NLG: 意思-> 文本

机器翻译系统实现

Decoding Algarithm
Viterb

NLP 应用案例

  • Question Answering问答系统(IBM)
  • Sentiment Analysis情感分析
  • Machine Translation 机器翻译
  • Text Summarization 自动摘要
  • Chatbot 聊天机器人
  • Information Extraction 信息抽取

自然语言处理技术的四个维度

  • Semantic 语义
  • Syntax 句子结构
  • Morphology 单词 NER 命名实体识别
  • Phonetics 声音

NLP关键技术

  • Word Segmentation (分词)
  • Part-of-Speech 词性
  • Named Entity Recognition 命名实体识别
  • Dependency Parsing 依存分析
  • Relation Extraction 关系抽取

文本处理过程

原始文本 -> 分词(Segmentation) -> 清洗(Cleaning)(无用的标签, 特殊符号,停用词,大小写转换) -> 标准化(Normalization) -> 特征提取 -> 建模 -> 评估

  1. Word Segmentation
  2. Spell Correction
  3. Filtering Words Stop Words Removal
  4. Stemming

Word Segmentation Tools

  • Jieba分词
  • SnowNLP
  • LTP
  • HanNLP

分词工具实现:

  • 基于匹配规则的方法
    最大匹配(Max Matching) 前向最大匹配(forward-max matching) 后向最大匹配(backward-max matching)
  • 基于概率统计的方法
    Incorporate Semantic(考虑语义)
    language model 维特比算法
    LM,HMM,CRF

Spell Correction(拼写错误纠正)
计算编辑距离 insert delete replace

Flitering Words
把停用词和出现频率低的词过滤

Stemming/lemmatization 相同含义单词合并
Porter Stemmer 算法

文本表示 Word Representation
词表示 one-hot representation
句子表示 Boolean representation
Count-based representation
tfidf(w) = tf(d, w) * idf(w)
tf(d,w)表示文档d中w的词频
idf(w)考虑单词的重要性 logN/N(w) N语料库中的文档总数 N(w)词语w出现在多少个文档
句子相似度 Sentence Similarity
欧式距离: d = |s1 - s2|
余弦相似度: d = (s1 * s2)/(|s1| * |s2|)

one-hot representation 缺点
没办法表示单词间语义的相似度
Sparsity 稀疏性

分布式表示法 Distributed Representation
词向量(word vectors)

词向量表达句子向量

  1. 平均法则
  2. LSTM/RNN

训练词向量的常用模型
Skip-Gram
G-lone
CBow
RNN/LSTM
MF

Noisy Channel Model
p(text|source) 等比 p(source|text)p(text)
应用场景
语音识别 P(文本|语音信号) 等比 P(语音信号|文本) * P(文本)
机器翻译 P(中文|英文) 等比 P(英文|中文) * P(中文)
拼写纠错 P(正确写法|错误写法) 等比 P(错误写法|正确写法) * P(正确写法)
OCR
密码破译 P(明文|暗文) 等比 P(暗文|明文) * P(明文)

语言模型 Language Model
作用:是否一句话从语法上是通顺的

Chain Rule
p(w1,w2, w3,w4,w5,…wn) = p(w1) * p(w2|w1) * p(w3|w1w2)….p(wn|w1w2…wn_1)

Markov Assumption 马尔可夫假设 解决稀疏问题
1st order | 2st order | 3rd order

语言模型分类:
Unigram: 每个单词是独立个体,相互独立 P(w1, w2, w3, w4 … wn) = p(w1) * p(w2) * p(w3) … p(wn)
Bigran: 1st order Markov Assumption P(w1, w2, w3, w4 … wn) = p(w1) * p(w2|w1) * p(w3|w2) … p(wn|wn_1)
N-gram:

使用Estimating Probability 计算每个单词的概率,但是会出现概率0项,可做平滑

如何评估语言模型
$ Perplexity = 2^{-(x)} $

处理未出现在字典中的词

  1. Add-one Smoothing (Laplace Smoothing)
    $ P_{ADD-1}(w_i|w_{i-1}) = \frac{c(w_{i-1}, w_i) + 1}{c(w_i) + V} $
  2. Add-k Smoothing
    $ P_{ADD-1}(w_i|w_{i-1}) = \frac{c(w_{i-1}, w_i) + k}{c(w_i) + kV} $
    如何选择k
    1. k = 1,2,3尝试
    2. 优化 f(k) 使用Preplexity优化
  3. Interpolation
    $p(w_n|w_{n-1}, w_{n-1}) = \lambda_1 p(w_n| w_{n-1}, w_{n-2}) + \lambda_2 p(w_n| w_{n-1} + \lambda_3 p(w_n)$
    $ \lambda_1 + \lambda_2 + \lambda_3 = 1$
  4. Good-Turning Smoothing
    缺点:

语言模型

pandas

贪心算法 每次选择当前最好的 局部最优
DP 全局最优

tf.data.Dataset.from_tensor_slices

入参

一个元组、列表和张量

出参

得到数据集,类型为TensorSliceDataset

作用

是把给定的元组、列表和张量等数据进行特征切片。切片的范围是从最外层维度开始的。如果有多个特征进行组合,那么一次切片是把每个组合的最外维度的数据切开,分成一组一组的。

假设我们现在有两组数据,分别是特征和标签,我们假设每两个特征对应一个标签。之后把特征和标签组合成一个tuple,那么我们的想法是让每个标签都恰好对应2个特征,而且像直接切片,比如:[f11, f12] [t1]。f11表示第一个数据的第一个特征,f12表示第1个数据的第二个特征,t1表示第一个数据标签。那么tf.data.Dataset.from_tensor_slices就是做了这件事情:

line_number: true
1
2
3
4
5
6
7
8
9
import tensorflow as tf
import numpy as np

features, labels = (np.random.sample((6, 3)), # 模拟6组数据,每组数据3个特征
np.random.sample((6, 1))) # 模拟6组数据,每组数据对应一个标签,注意两者的维数必须匹配

print((features, labels)) # 输出下组合的数据
data = tf.data.Dataset.from_tensor_slices((features, labels))
print(data)

实战使用keras的mnist数据集,使用GAN生成手写数据图片

使用生成器模型生成手写图片
使用判别器模型对真图片进行真判断对生成的图片进行假判断

定义生成器模型

生成器用来将随机数生成手写数据图片
生成器使用三层结构
输入层和中间层使用BatchNormalization进行标准化,使用LeakyReLU进行激活
输出层使用tanh激活
最后将输出数据改为28 * 28 * 1 的形状

line_number: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def generator_model():
model = tf.keras.Sequential()
model.add(keras.layers.Dense(256, input_shape = (100,), use_bias = False))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.LeakyReLU())

model.add(keras.layers.Dense(512, use_bias = False))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.LeakyReLU())

model.add(keras.layers.Dense(28 * 28 * 1, use_bias = False, activation = 'tanh'))
model.add(keras.layers.BatchNormalization())

model.add(keras.layers.Reshape((28, 28, 1)))

return model

定义判别器模型

判别器用来对输入图片进行判别
判别器使用三层网络结构
第一层将图片数据延展并输入到一个全连接层,使用BatchNormalization标准化,使用LeakyReLU激活
第二层是个全连接层,同样使用使用BatchNormalization标准化,使用LeakyReLU激活
第三层输出判别的结果

line_number: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def discriminator_model():
model = keras.Sequential()
model.add(keras.layers.Flatten())

model.add(keras.layers.Dense(512, use_bias = False))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.LeakyReLU())

model.add(keras.layers.Dense(256, use_bias = False))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.LeakyReLU())

model.add(keras.layers.Dense(1))

return model

GAN 生成对抗网络

应用领域

* 图像生成
* 图像增强
* 风格化
* 艺术的图像创作

GAN定义

GAN 包含两部分生成器generator与判别器discriminator,
* 生成器主要用来学习真实图像分布从而让自身生成的图像更加真实,以骗过判别器
* 判别器对接收的图片进行真假判断

GAN 设计

  • 生成器网络

  • 判别器网络(例如 5层CNN)

自编码器
基本去燥自编ma
卷积去燥自编码器

GAN自定义

将数据页从磁盘读入内存中涉及随机IO访问,这也是数据库里面成本最高的操作之一,而利用写缓存(Change Buffer)可以减少IO操作,从而提升数据库性能。

Read more »

https://juejin.im/post/5e575cb56fb9a07c951cdb39?utm_source=gold_browser_extension

自从两年前了解到的索引以来的,就一直想写一篇有关索引的文章。然而我是个拖延癌症患者,一拖就是两年,不愧是我。该篇文章算是自己的笔记,欢迎批评。
概述
索引是什么?很多书和文章都会使用图书的目录来类比。目录的目的就是用方便我们查找具体内容的位置,具体的章节的范围。与此类似,MySQL中索引的用途是帮助我们加速查询以及排序。
在InnoDB中的索引类型有哈希索引、B+树索引、全文索引。哈希索引在InnoDB中设计为自适应的,不展开讨论。在InnoDB1.12之后有了全文索引,也是应用倒排,还没踩过坑(据说不支持中文),有时间可以研究一下。
本篇主要讨论B+树索引。
B+树
学习MySQL的索引,必须得先了解其原理,否则很多问题将一头雾水。下文将讲述索引数据结构的原理,而不涉及其复杂的具体实现。
在谈B+树之前,不妨先思考,为什么索引能加快查询?为什么要用B+树作为索引而不用B树?哈希索引查询复杂度为O(1)为什么又不用哈希索引?
BST和AVL
在了解B树和B+树之前,先了解一下二叉搜索树(BST)和平衡二叉树(AVL)。
在顺序存储结构中(如数组),最快的情况是第一个就是目标值,最坏的情况是最后一个是目标值,假设有n个元素,用大O标记法平均的时间复杂度为O(n)。
使用二叉搜索树可以有效的优化搜索时间。利用二叉搜索树的特性左子节点比父节点小、右子节点比父节点大,可以很方便的进行二分查找,有效优化的搜索时间。

正常情况下,我们使用二叉搜索树可以了,但如果出现以下的情况,二叉搜索树反而起不到效果,搜索的平均时间复杂度依旧为O(n)。

引入平衡二叉树,深度差不超过1,从而保证不倾斜,或者说更矮,保证其搜索效率。
B树和B+树
既然平衡二叉树已经可以加快查询了,但实际上InnoDB并不会使用。在思考B树和B+树的相关问题的时候,离不开一个问题——磁盘IO。索引文件存储在磁盘,假设有平衡二叉树树高30,那么你可能要扫描30次磁盘才能完成搜索。
对于需要磁盘IO的情况,使用平衡二叉树依旧比较糟糕,所以需要引入多路树,即B树和B+树,使得树更“矮”。

如果上述B树改成二叉树,那么树的高度就大了很多,换而言之就需要更多次的磁盘IO。
B+树是B树的变种。B+树的非叶子结点不存储数据,并且所有的叶子节点以双向链表的形式相连。

现在的索引模型基本都是B+树。
相对于B树来说,B+树的搜索更加稳定,因为B树有的数据是分布在非叶子节点上的。
B树的叶子节点以链表的形式相连且按照规则排了序,通过B+索引,可以更加方便的获取范围数据。
这也是不使用哈希索引的原因。虽然哈希索引搜索的时间复杂度为O(1),但大部分时候我们并不会只查询一条记录,这种时候使用哈希索引就比较乏力了。
聚集索引
聚集索引,亦可称为主键索引。一张表只存在一个聚集索引。
聚集索引是根据其主键作为排序规则的B+树,搜索时根据其主键进行搜索。
其中叶子节点上存储着整条记录的数据。
InnoDB的B+树在磁盘中的存储是以数据页的形式,在树中间进行插入和删除操作涉及列“页分裂”和“页合并”的复杂过程(关于这点我个人也讲不明白,但可以类比AVL树的旋转去理解),十分耗性能,而直接插入尾部是比较快捷的方式,所以在很多的规范中写道,当使用InnoDB引擎的时候,强烈建议用一个与业务无关的自增id作为主键。
此外,删除也是一样的,很多时候会要求做伪删除,不仅仅只是为了数据分析,更是为了索引的性能。
非聚集索引
非聚集索引又称辅助索引,以非主键列来建立。非聚集索引可以有多个。非聚集索引和聚集索引的区别在于,非聚集索引的叶子节点并不存储整条记录的数据,而是存储指向的主键的指针。所以,当利用非主键索引进行搜索时,还需要通过主键索引获取整条数据。
单值索引
单值索引就是在数据表单个列上建立单个值。
CREATE INDEX index_name ON table_name(column);
复制代码与主键索引类似,单值索引按照所指定列排序建立二叉树。当利用单值搜索到目标后,再通过主键索引去读取整条数据。
唯一索引
唯一索引与单值索引区别不大,只是唯一索引的值不会重复。
唯一索引除了能提高一些效率以外,有时也用来保证列的唯一性,如用户的手机号身份证等。这里不做过多赘述。
联合索引
创建联合索引时指定多列即可。
CREATE INDEX index_name ON table_name(column1, columm2, column3 [,…])
复制代码联合索引会按照建立索引时的顺序,对每个字段进行排序。即第一个字段排完序,接着排第二个字段,第三…

覆盖索引
在前面提到,非聚集索引搜索记录时还需要通过的主键索引,但如果查找的列刚刚好是联合索引的字段,那就没有必要去再去搜索主键索引,直接取叶子节点值即可,这就是覆盖索引。
为什么不用select *,原因就在此,不仅仅是为了减少读取更多列带来的开销,也是为了能够使用上覆盖索引。使用覆盖索引可以减少磁盘IO,有效提高性能。
下文将讲述有关联合索引的更多细节。
最左前缀原则
上文了解了联合索引,知道了联合索引的节点数据是按照建索引的顺序依次排序,由此我们引出了最左前缀原则,联合索引中,如果要用上索引字段,前面的字段不能跳过。如果上图的例子,假设是找column2=“ccc”的记录,大概的sql如下
SELECT some_column FROM table_name WHERE column2=”ccc”
复制代码这种情况下索引是用不上的,因为索引是先排序的column1,再排序column2,直接通过column2搜索,B+树并不知道怎么搜索。
索引失效
除了上述的最左前缀原则下索引的失效,还有其他索引失效情况。

使用MySQL内置函数运算的列索引会失效。

使用!=,is null,is not null 索引会失效。
比如你查找id != 500的记录,相当把扫描id<500,以及id >500的记录,本质上全表扫描没啥区别。

范围查询后的列无法使用。
还是用上图的例子,假设查询 column1 <= 4的情况
SELECT some_column FROM table_name WHERE column1 <= 4
复制代码因为column1是排了序的,索引联合索引column1还是可以使用上的,但column1是范围数据,在这范围内column2并不有序。

以通配符开头的模糊查询(LIKE “%string”)。
值得一提的是,LIKE “string%”是能用上索引的,类似于范围查询,查询从string开头的最小字符串到stirng开头的最大字符串。知道了LIKE “string%”是能用上索引的就能理解为什么LIKE “%string”为什么用不上索引了。

还有其他情况的情况,可用MySQL的查询分析器进行分析。
InooDB使用的锁是行锁,但如果在更新时索引失效了,行锁会变成表锁,在开发中应该避免。
索引使用tip

常用来分组和排序的字段可建立索引。
索引的作用是查询和排序,order by和group by是可以用上索引的,如果排序的有多字段,也是按照最左前缀原则。

经常用来查询的字段可建索引。

更新频繁的字段不要建立索引。
频繁更新的字段如果建立来索引,更新时不仅更新数据,而且索引的B+树也会发生变化,开销比较大,得不偿失。

选择性小的列不要建立索引。
比如说性别字段,只有男或女或未知,百万数据里只有这三个值,建立索引毫无意义。

索引尽量使用等值匹配。

尽量使用覆盖索引。

小结
通过建立索引,可以有效的加速数据库的查询和排序。当谈及的数据库优化时,索引优化肯定跑不了。索引的使用有各业界大佬总结的技巧,但很多东西不是绝对的,不能以偏概全,在大数据以及复杂业务下,索引的维护算是玄学,需要不断寻找最佳的索引方案。

奇偶判断

if( n & 2 == 1){
dosomething();
}

利用n & (n - 1)消去n最后的一位1

(1)、判断一个正整数n是否为2的幂次方
如果一个数是 2 的幂次方,意味着 n 的二进制表示中,只有一个位 是1,其他都是0。我举个例子,例如
2^0 = 0…..0001
2^1 = 0…..0010
2^2 = 0….0100
那么我们完全可以对n执行n = n & (n - 1),执行之后结果如果不为 0,则代表 n 不是 2 的幂次方,代码如下

(2)判断正整数n的二进制表示中有多少个 1
我们可以用不断着执行 n & (n - 1),每执行一次就可以消去一个 1,当 n 为 0 时,计算总共执行了多少次即可

异或(^)运算的妙用

特性一:两个相同的数相互异或,运算结果为 0,例如 n ^ n = 0
特性二:任何数和 0 异或,运算结果不变,例如 n ^ 0 = n
特性三:支持交换律和结合律,例如 x ^ ( y ^ x) = (x ^ y) ^ x

案例1:只出现一次是数

定义

MySQL存储引擎也称作表类型是指,MySQL使用的不同的存储技术将数据存储在文件(或者内存)中。
这些技术指不同的存储机制、索引技巧、锁定水平等。

实例

需要根据不同的应用场景选择不同的数据引擎
例如:研究大量的临时数据需要选择内存存储引擎
需要处理事务型的业务需要选择支持事务性的数据库

常用引擎及其特性

MyISAM: 拥有较高的插入,查询速度,但不支持事务
InnoDB:事务型数据库的首选引擎,支持ACID事务,支持行级锁定
CSV: 逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每个数据表创建一个.CSV文件。这是一种普通文本文件,每个数据行占用一个文本行。CSV存储引擎不支持索引