日志

CNN-卷积神经网络

CNN 的核心思想:局部感受野(local field) + 权值共享 + 亚采样 。

1
CNN 主要由四类层(layer)组成,即卷积层(Conv)、激活层(Activation)、池化层(Pooling) 以及全连接层(FC/Dense)。

卷积层(Convolution)

传统神经网络采用全连接的方式,往往容易导致需要训练的参数非常庞大,甚至难以训练,卷积神经网络通过卷积层的“局部连接”和“参数共享”的特性大大减少训练参数。

举例:输入 100 x 100, 隐藏层有10个神经元

传统全连接方式(Full Connected)
输入 100 x 100 与每一个神经元连接,需要训练 100 x 100 x 10 = 100000 个参数(不考虑bias)

局部连接(Sparse Connectivity)
假设每个神经元只与局部 10 x 10 个输入连接,那么只需要训练 10 x 10 x 10 = 1000 个参数!!

权值共享(Shared Weights)
如果每个神经元的连接使用相同的权值,那么实际训练参数进一步压缩到 10 x 10 x 1 = 100 个参数!!

卷积层如何生成

卷积核 (或称滤波器,filter/kernel)

2
上图是一个尺寸为 3×3 的卷积核, 即每个神经元由输入的 3×3 局部连接所得,卷积核的值通过训练来学习。

卷积核的 stride 值

3
stride 指卷积核的移动步长(这其实就是权值共享的表现),上图 stride=2,卷积核每次移动两个单元。

卷积核的 padding 值

4
padding 即在输入矩阵的四周添加填充,一方面可以减少原输入的边缘影响,另一方面可以用于维持输入和输出的维度一致(需要 stride 配合)。

padding 的常见术语包括:
(1) valid: 即 no padding
(2) same:通过填充使得输入和输出的维度保持一致

输出维度计算(取下界)
8

卷积输出-Feature Map(特征图)

实际上卷积核的作用就是对输入层进行特征学习,卷积核可以看成是对输入的一种特征映射,通过这种特征映射,一个卷积核对应生成一个特征图(Feature Map),即上图的 Result。

多通道卷积

5
当输入有多个通道(channel)时(例如图片可以有 RGB 三个通道),卷积核需要拥有相同的channel数,每个卷积核 channel 与输入层的对应 channel 进行卷积,将每个 channel 的卷积结果按位相加得到最终的 Feature Map。

多卷积核

6
当有多个卷积核时,可以学习到多种不同的特征,对应产生包含多个 channel 的 Feature Map, 例如上图有两个 filter,所以 output 有两个 channel。

为什么不需要全连接而只需要局部连接就会有效果?

对于图像而言,局部区域的像素关联性往往很强,而相距较远的区域关联性往往很弱。同样,对于文本而言,相近的词汇在语义表达上往往有紧密联系而相隔较远的词汇语义关联则相对较低。因此,只需要对局部信息进行特征提取,最后综合起来就能达到全局感知。

激活层(Activation)

阅读全文

日志

RNN/LSTM-递归神经网络

关于递归神经网络的理论介绍推荐阅读这篇非常经典的文章 → Understanding LSTM Networks
本文为总结笔记

一、RNN vs LSTM

RNN 逻辑结构图

1

LSTM 逻辑结构图

2

LSTM 是 RNN 的变体,它们的原理几乎一样,唯一的不同是 output 即 hidden state 的计算逻辑不同

RNN 如何计算某个时刻 t 的 output ?

h_t = tanh(W*[h_{t-1}, x_t]+b)

LSTM 如何计算某个时刻 t 的 output ?

遗忘门(Forget Gate): 控制遗忘哪些记忆(Cell state)

f_t = sigmoid(W_f*[h_{t-1}, x_t] + b_f)

新信息:候选记忆信息

{C}^{*} = tanh(W_c*[h_{t-1}, x_t]+b_c)

输入门(Input Gate):控制加入哪些新信息到记忆中

i_t = sigmoid(W_i*[h_{t-1}, x_t] + b_i)

新记忆:遗忘部分旧记忆,加入部分新记忆信息,得到最新的cell state

C_t = f_t*C_{t-1} + i_t*{C}^{*}

输出门(Output Gate):控制当前最新记忆的对应输出值

o_t = sigmoid(W_o*[h_{t-1}, x_t] + b_o)

输出值:最终的 hidden state

h_t = o_t*tanh(C_t)

当 Forget Gate=0, Input Gate=1, Output Gate=1 时 LSTM 与 RNN 等价

LSTM 为什么优于 RNN ?

RNN 通过叠乘的方式进行状态更新,当 sequence 比较长时容易出现梯度消失/爆炸的情况,主要原因是反向传播的连乘效应,而 LSTM 是通过门控制的叠加方式来更新状态(C_t的计算公式),所以可以有效防止梯度问题,当然对于超长的 sequence,LSTM 依然会有梯度消失或者爆炸的可能。

二、RNN/LSTM 中的 num_units 是啥意思 ?

3
num_units 相当于神经网络的隐层神经元的个数,例如上图表示一个 LSTM Cell,包含四个神经网络层,即黄色方框部分,num_units 就是每个神经网络结构的隐层神经元个数(全连接单元数),它实际上也是 LSTM 输出向量的维度数,所以 h_t 为 num_units 维向量。

三、如何计算 Keras 的 LSTM layer 的参数个数?

假设 LSTM(num_units = 150),输入维度 input_dims = 100,那么共需要训练的参数个数为:

(num\_units + input\_dims + 1) * num\_units * 4 = 150600

说明:
1. num_units + input_dims 是因为上层输出需要首先与输入进行一次concat,即 [h_t-1, x_t],
2. + 1 是因为 bias
3. * 4 是因为共有4个神经网络层(黄色方框)
4. 为什么不需要乘以 time_steps 即 number of cell ?
因为递归神经网络的每个 cell 实际上只是在不同时态下的状态,所以不同 cell 共用同一套权重,文章开头的结构图只是为了理解方便而将递归过程展开,实际上任何时候都只存在一个 cell !!

四、为什么 LSTM 要用 sigmoid 作为门控激活函数 ?

因为sigmoid的输出在0~1之间,可以很好地控制信息的删除和保留。

五、为什么 LSTM 的输入和输出值不用 sigmoid 而用 tanh 作为激活函数 ?

LSTM 内部维护了一个状态向量,其值应该可以增加或者减少,而 sigmoid 的输出为非负数,所以状态信息只能增加,显然不合适,相反,tanh 的输出范围包含了正负数,因此可以满足状态的增减。

六、什么是 sequence?

阅读全文

日志

Batch Normalization

Batch Normalization(简称 BN)是指对上一层的输出或者激活层的输入做标准化处理,从而使得激活层的输入值的分布更合适,进而加快收敛速度。

1

上图表示一个多层神经网络在采用 BN 层和不采用 BN 层时不同层的对应输出分布,可见不使用 BN 层的输出大部分分布在两端,而使用 BN 层的输出分布则比较均衡。

什么是 Batch Normalization

standard-normal-distribution-6
Batch Normalization 是指将线性激活函数的输入值变换为标准正态分布(均值为0,方差为1),使得其分布在激活函数的敏感区,从而加快收敛。如果不这么做,一旦激活函数的输入值分布在激活函数的极限饱和区,那么激活函数的梯度就会接近消失,从而无法更新参数或者参数更新很慢,进而影响模型的学习。
2
例如:sigmoid 函数,敏感区在[-2,2],两端的梯度逐渐消失,如果将输入变换为正态分布,那么95%的落点都在敏感区,有效避免梯度消失问题。

一味将输入值通过正态变换使得其落在敏感区也有问题,因为敏感区往往是偏线性的,这样会影响模型的表达能力,相当于失去了激活函数的意义(激活函数通过让模型损失一些输入信息从而达到非线性效果,例如 sigmoid 的两端),因此 BN 层还会通过 scale(γ斜率,即缩放,可以看成对方差的调整)和 shift(β截距,即移位, 可以看成对均值的调整)的操作使得落点分布在线性与非线性上获得平衡。

Relu 激活函数是否适合前接一个BN?
3
适合。通过 Batch Normalization 后,输入95%分布在(-2,2)大概有一半的输入得到激活,且保留非线性。

如何计算 Batch Normalization 的输出值

首先进行正态变换:
CodeCogsEqn
其中 E(x) 表示一个 batch 的均值,var(x) 表示一个 batch 的方差。(计算全局均值、方差需要非常大的计算开销,计算 batch 则非常高效,也许这就是为什么叫 Batch Normalization 的原因)

再通过 scale 和 shift 计算最终输出:
6
其中 γ 和 β 是要学习的参数。

举例:对于一个 batch_size 为 N, 宽为 P, 高为 Q 的特征图,一个 batch 的均值和方差就是基于这 N x P x Q 个特征计算所得,一个特征图学习一组 γ 和 β。

Batch Normalization 的优点

1.收敛更快,减少了训练时间(因为降低了梯度爆炸/消失的风险)。
2.减少了对正则化(dropout、L2)的需求,因为BN标准化是基于 batch 来计算均值和方差的,所以每个标准化产生的值都取决于当前的 batch,这本身就是一种正则化的体现。
3.允许设置更高的学习率(因为降低了梯度爆炸/消失的风险)。

Batch Normalization 的使用需要注意什么

1.由于均值和方差是针对 batch 计算的,所以如果 batch 太少,引入 BN 可能会有副作用。
2.对于不平衡的数据集,引入 BN 可能会导致更差的 Performance,因为对于不平衡语料,BN 不但没有做到“标准化”反而让不平衡的问题更加突出。

转载请注明出处:

© http://hejunhao.me

日志

Spark 大规模稀疏矩阵乘法

spark 可以通过 BlockMatrix 进行矩阵相乘,但其在大规模稀疏矩阵场景有非常严重的性能问题,本文通过基于 RDD 和 DataFrame 两种方式实现基于 spark 的大规模稀疏矩阵乘法运算。

一、矩阵乘法运算

1

二、通过 BlockMatrix 进行矩阵相乘

3

from pyspark.mllib.linalg.distributed import *
from pyspark.sql import SparkSession

ss = SparkSession.builder.appName("test") \
    .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") \
    .getOrCreate()

sc = ss.sparkContext
sc.setLogLevel("WARN")

M_rdd = sc.parallelize([(0,0, 1), (0,1, 2), (0,2, 3), (1,0, 4), (1,1, 5), (1,2, 6)])
N_rdd = sc.parallelize([(0,0, 7), (0,1, 8), (1,0, 9), (1,1, 10), (2,0, 11), (2,1, 12)])
M = CoordinateMatrix(M_rdd).toBlockMatrix()
N = CoordinateMatrix(N_rdd).toBlockMatrix()
M.multiply(N).toCoordinateMatrix().entries.collect()

######## 输出 #############
# [MatrixEntry(0, 0, 58.0),
#  MatrixEntry(1, 0, 139.0),
#  MatrixEntry(0, 1, 64.0),
#  MatrixEntry(1, 1, 154.0)]

三、BlockMatrix 的性能问题

在 spark 的官方文档中关于 multiply 这个方法的描述如下

Left multiplies this BlockMatrix by other, another BlockMatrix. The colsPerBlock of this matrix must equal the rowsPerBlock of other. If other contains any SparseMatrix blocks, they will have to be converted to DenseMatrix blocks. The output BlockMatrix will only consist of DenseMatrix blocks. This may cause some performance issues until support for multiplying two sparse matrices is added.

也就是说,BlockMatrix 在进行矩阵乘法时会先把稀疏矩阵转换成稠密矩阵!!对于一个 10000 x 10000 的稀疏矩阵,实际存储的可能只有几万个非零元素,而转换成稠密矩阵后,你需要对所有 10000 x 10000 = 1亿 个元素提供存储空间!!而实际场景面对的稀疏矩阵的维度远远大于 10000,所以 BlockMatrix 无法适用于大规模稀疏矩阵运算。

四、矩阵乘法公式

CodeCogsEqn
图片 1
从矩阵乘法公式可知,矩阵相乘主要有以下环节:
1.左矩阵的列号(j)与右矩阵的行号(j)相同的元素进行两两相乘得到 MN_ik。
2.对所有具有相同下标(ik)的 MN_ik 进行相加,即得到 P_ik。

五、基于 RDD 实现矩阵乘法

阅读全文

日志

基于 CCO 的协同过滤推荐

基于 CCO(Correlated Cross-Occurrence) 的协同过滤本质上是一种 Item-Based CF 算法

基于 CCO 的协同过滤推荐

基于 CCO 的协同过滤推荐通过物品之间的共现情况来计算物品之间的关联度,它跟一般的协同过滤算法不同的地方在于一般的协同过滤只能针对单一行为,而CCO算法可以计算交叉行为下的协同关联。

例如:它不仅可以通过用户的浏览行为来告诉你 “浏览了内容A的人可能会浏览内容B” ,它还能结合用户的浏览行为和用户的广告点击行为来告诉你 “点击了广告A的人可能会浏览内容F”

基于单一行为

假设有以下用户浏览行为日志:
用户行为log

整理后得到以下关系:
u1=> [ t1, t2, t3, t5 ]
u2=> [ t1, t3, t4, t5 ]
u3=> [ t2, t4 ]

构建 “用户关于浏览帖子” 的矩阵 V 以及对应的转置矩阵 V^T:
mtV

将 矩阵V^T 乘以 矩阵 V 即可得到浏览帖子的共现矩阵:
mtVV

对数似然比(Log Likelihood Ratio)即LLR。我们根据两个事件的共现关系计算LLR值,用于衡量两个事件的关联度:
LLR
阅读全文

日志

常用推荐算法比较

在推荐系统中常用的推荐算法一般可以分为两类,即 基于内容推荐 以及 协同过滤。另外,还有一类算法专门处理冷启动问题,例如:基于全局最优推荐

基于内容推荐

基于内容推荐(Content-based Recommendations)非常好理解,简单来说就是根据用户偏好的内容给他推荐其他相似的内容。

cb

图:基于内容推荐

例如:从用户画像我们发现某个用户比较喜欢活跃在“音乐”、“体育”、“动漫”、“影视” 这些栏目,那么我们就会更倾向推荐这些栏目的内容给他,我们还发现他平时偏好的是关于 “NBA”、“美剧”、“邓紫棋” 等方面的内容,那么跟这些相关的内容就会有更高的推荐权重。

评价

基于内容推荐的结果一般具有很强的解释性,因为它推荐的就是强相关的内容,但这种强相关的特点也会导致一个很明显的缺陷,它缺乏惊喜度,因此它很难挖掘用户潜在的兴趣。要解决惊喜度的问题,可以采用另一类算法–协同过滤

协同过滤

协同过滤(Collaborative Filtering)推荐本质上也是一个找相似的过程,但它认为的相似不是指物品在属性上的相似,而是指在用户行为的层面上这些物品是否有关联,协同过滤一般可以分为 基于用户的协同过滤(User-CF)基于物品的协同过滤(Item-CF)

用户物品偏好

图:用户物品偏好

基于用户的协同过滤

解释:因为 用户1用户2 都喜欢物品A、B、C、D、E,所以认为 用户1用户2 是兴趣相似的用户,现在发现 用户2 还喜欢 物品F 所以我们认为 用户1 很可能也对 物品F 感兴趣,所以向 用户1 推荐 物品F。

基于物品的协同过滤

解释:因为喜欢 物品A 的大多数都喜欢 物品C,所以可以认为 物品A 和 物品C 是相似的。用户4 喜欢 物品A 所以向 用户4 推荐 物品C。

评价

协同过滤集合了群体智慧,能满足推荐惊喜度,善于发掘用户潜在的兴趣。训练的用户历史行为数据越多,一般训练出来的模型效果也会越好。协同过滤推荐的解释性一般较弱,推荐结果不如基于内容推荐算法直观,当然这是算法特点导致的,不直观不等于不正确
阅读全文

日志

个性化推荐系统的基本抽象

在大多数 UGC、PGC、OGC 平台中,“推荐”随处可见,本文主要介绍个性化推荐系统的抽象组成。

关于推荐

人工 VS 个性化

  • 早期的推荐功能大多以人工筛选为主。人工筛选可以确保内容的高质量,这是主要的优点之一,但人工筛选往往需要投入大量的人力成本。另外,由于不同用户的个人偏好差异巨大,高质量的内容往往不等于最合适的内容(例如:一篇介绍奢侈品牌化妆品的“高大上”内容对于一位平时只关心美食和户外运动的用户而言可能是毫无吸引力的)。

  • 为了提升用户体验,后来出现了“个性化内容推荐”的概念,通过引入个性化推荐系统,解决这类“千人千面”的问题。

推荐系统抽象

个性化推荐系统一般有三大环节:预处理 -> 召回 -> 排序
注:也可以认为是两层(召回 -> 排序)

预处理

第一个环节是预处理,预处理指的是对各种数据源的数据进行特征提取和特征构建,例如:内容特征提取,用户行为画像构建。

召回

第二个环节是召回,召回就是把预处理产生的特征作为输入参数,训练出推荐模型,然后使用推荐模型得出候选集合的过程。常用的召回方式有:基于内容推荐、基于协同过滤推荐等。

排序

第三个环节是排序,简单来说就是将候选集合根据一定的规则,例如:点击预估、匹配关联度、人为权重等进行调整,从而影响最后的推荐顺序。

推荐系统架构

最后简单画了一个基本的推荐系统架构原型
个性化推荐系统框架

图:个性化推荐系统架构 ©️hejunhao.me
转载请注明出处:

© http://hejunhao.me

日志

基于词向量的文本分类推断

之前的文章中介绍过提取文本标签特征(关键词)的几种算法TF-IDFTextRankTWE, 提取到标签特征后,我们可以进一步推断文本的内容分类。本文主要介绍通过词向量模型进行内容分类的一般思路。

提取文本标签特征

假设有以下一段文本:

2016/17赛季欧冠决赛在威尔士卡迪夫千年球场打响,最终尤文图斯以1-4不敌皇家马德里,遗憾错失冠军。赛后,尤文门将布冯表示对结果非常失望,因为尤文已经做了所有能做的事情。

通过关键词提取算法我们提取到以下标签:
#欧冠#决赛#尤文图斯#皇家马德里#布冯#门将#球场#冠军

假设我们有一个关于体育的分类体系:
分类体系

图:分类体系
  • 一级分类:体育
  • 二级分类:篮球(关联标签:NBA,CBA,篮球,篮板球,助攻,盖帽,FIBA,姚明,乔丹,三双…)
  • 二级分类:足球(关联标签:世界杯,亚冠,欧冠,中超,足球,英超,西甲,梅西,里皮,马拉多纳,门将,广州恒大,曼联…)

分类推断

通过词向量模型(Word2Vec)我们可以计算两个词之间的相似度(余弦距离):

Similarity(tagA, tagB) = cos(tagA_Vec, tagB_Vec)

因此,计算文本与分类的相似度实际上就是计算文本的标签与各个分类的关联标签的相似度。
我们发现上面这段文本与足球的相似度大于与篮球的相似度:

Dist(doc_tags, soccer_tags) > Dist(doc_tags, basketball_tags)

所以推断它是关于足球的内容,再进一步把它归类到体育这个一级分类。

转载请注明出处:

© http://hejunhao.me

日志

基于 TWE 模型的关键词提取

在之前的两篇文章中分别介绍了两种常见的关键词提取算法:TF-IDFTextRank。实际上不管是 TF-IDF 还是 TextRank,它们都没有考虑文本的语义,也就是文本的内容意义。为了进一步提升效果,我们引入主题模型(LDA)和词向量模型(word2vec)也就是TWE算法。

TWE (Topical Word Embedding)

主题模型

LDA

图:主题向量模型
  • 在主题模型中每个主题实际上是一系列代表该主题的词的分布 ,例如:上图主题 Topic#1 包含的主题词分布主要有 “红包”、“微信”、“支付宝”、“玩法”等,文字大小代表该词的概率分布差异,可以推断 Topic#1 是一个关于新年红包活动的主题。

词向量模型

word2vec

图:词向量模型
  • 在词向量模型中每个词都有自己的坐标,关联度越高的词相互的距离越近。例如:“梅西” 和 “足球” 的距离比 “奥巴马” 与 “足球” 的距离要近得多,所以 “梅西” 与 “足球” 的关联度相比 “奥巴马” 更高。

基于 TWE 提取关键词

  1. 通过主题模型我们可以知道一段文本的主题分布:P(topic | doc)
  2. 结合词向量和主题向量,我们可以通过余弦函数计算两者的距离:cos(word_vec, topic_vec)
  3. 通过计算词向量与该文本所有关联主题的主题向量的余弦相似度,最终得到词与文本的语义关联度:
Sim\displaystyle\text{(word, doc)}=\sum_{k=1}^K \cos(\text{word\_vec, topic\_vec}_{_k}) \times P(\text{topic}_{_k} \mid \text{doc})

算法比较

假设有以下一段文本:
文本
分别对该文本采用 TF-IDFTextRank 以及 TWE 算法提取关键词,结果如下:
算法对比

效果评价

  1. TF-IDF 更倾向于高频词。
  2. TextRank 综合考虑文本结构和词频,但它致命的问题在于,头尾的信息由于只有单边的入度,容易被抛弃掉,例如本例中的核心词 “pagerank”。
  3. TWE 更强调语义相关性,实际的提取效果也优于前面两种方式。

论文参考

转载请注明出处:

© http://hejunhao.me

日志

NLP 关键词提取算法之 TextRank

对文本提取关键词,除了经典的 TF-IDF 算法,还有另一种常用的算法 — TextRank

TextRank 介绍

TextRank 是一种基于图的排序算法,它的基本思想来自于著名的 Google PageRank.

PageRank via @Wikipedia

图:PageRank via @Wikipedia

PageRank 的基本思想

  • 一个网页的入链越多,它就越重要。
  • 如果一个网页被越重要的网页所指向,它也越重要。

TextRank 算法简释

下图是通过 TextRank 进行关键词提取的一个简单例子
例子

图:通过 TextRank 提取文本关键词

通过 TextRank 进行关键词提取的主要步骤

  1. 对文本进行分词,并去掉停用词以及非目标词性词汇。
  2. 通过一个固定长度的滑动窗口在分词文本上滑动,每个窗口内的词根据共现关系构建一条边,最终形成一个图。
  3. 对图进行 PageRank,实际上就是投票和迭代的过程。
  4. 选出权重最高的 TopK 个词。

算法总结

  • TextRank 算法一定程度上考虑了文本中词与词之间的关系,也就是文本结构,在实际应用中它的效果一般会比 TF-IDF 好,当然它的计算复杂度也比 TF-IDF 高得多。
  • TextRank 算法更擅长处理长文本,对短文本的效果并不理想,主要因为短文本的词汇信息较弱,构建的图并不理想。
  • TextRank 算法仍然倾向于选择出现较为频繁的词作为关键词。
转载请注明出处:

© http://hejunhao.me

第 1 页,共 5 页12345