特征分类
类别特征(Categorical Feature)
有限集合,当没有大小之分,是并列权重的
数值特征
如年龄、工资等,有大小之分

由于计算机只能处理数值型特征,因此需要将Gender列和Nationality列转化为计算机能识别的数字
此处Age为数字特征,性别为二元特征(Female:0,Male:1),国籍则是多元的类别特征
疑问:二元特征,也算一种特殊的类别特征,为什么不用二维向量表示?
类别特征转化为数字流程(以Nationality为例)
构建一个字典(US->1,China->2,India->3,German->4,...)
将特征转化为OneHot编码的向量(假设有197种国籍)
则每个国籍可以表示为197*1的向量,使用1中的字典查找国际Index(如Index(China)=2),则向量第二维为1,其它为0
"China"->2->[0,1,...,0]
将每一列的特征(Age,Gender,Nationality)转化为数字后,可以得到:
如:(Number,[Vector dim=1],[Vector dim=197])
(35,Male,China)=(35,1,[0,1,...,0])
为什么第一个要从1开始?
因为要保存0的编码来代表未知或缺失的国籍,即[0,...,0]来代表
为什么要用OneHot来表示Categorical特征?
因若不使用Onehot而用1,2,3,...代表US,China,India,...,则在此列特征运算时,”US“+"China"="India",显然是不合理的,而US:[1,0,0,...],China:[0,1,0,...]
US+China=[1,1,0,0,...]更能保留两种类型特征相加的信息
我们知道了如何处理类别型特征,但对于文本来说,又该如何处理文本文本数据呢?处理文本数据总体可以概括为以下几个步骤:
分词
以英文为例,将一个句子分为包含一个个的单词的列表
before:
S="... to be or not to be...".
after:
L=[...,to,be,or,not,to,be,...]
统计词频
1.构建一个字典,初始化一个空字典
2.从而可以得到一个字典
3.将字典中单词词频从大到小排序
4.再将词频转化为索引Index,转化完后的字典被称为词汇表"vocabulary"
由于词汇表通常会添加入一些不寻常的词,如名字、拼写错误的词等,因此需要对词汇表选择,可以在步骤3时截断出现次数\(time>1\)的单词,或设定词表大小为\(V\)
词表Index通常从1开始计数,原因是为OOV未登录词预留位置,出现时使用0编码
为什么要去除词表中多余的词?
One-Hot编码
得到了vacab即可将分词后的文本转化为向量
例如:
words:[to,be,or,not,to,be]
indices:[2,4,8,1,2,4]
再做OneHot
IMDB数据集:
50K movie reviews (text)
Each review is labeled with either “positive” or “negative”. •
It is a binary classification problem.
25K for training and 25K for test.
Download from
四个步骤:
分词前需要做的几件事:
将文本转化为数字序列
再将序列转化为矩阵
在对句子进行One-Hot编码后会存在一个问题,句子序列长度不一,有的长有的短

因此大于固定长度则截断,小于则补齐
一个单词可以用onehot向量表示(即只有一维为1,其它全为0),词向量的维度即为词表的长度。但由于OneHot向量的维度过高,会导致很多问题,因此需要做词嵌入来降低词向量的维度,做词嵌入有以下几步:


所以词嵌入的关键之处在于如何通过参数矩阵\(\rm{P}\)将OneHot向量映射,此参数矩阵是可以训练的,具体见Word2Vec的历史,词嵌入矩阵是实现上下文语义理解任务时的“副产物”
如下图为一个词嵌入矩阵:




几个组件:
初步工作描述:
SimpleRNN的核心运算如下:
\(h\)和\(x\)为向量\(h_t\)和\(x_t\)的维度,\(rand\_matrix\)函数随机初始化一个\(size=(h,h+x)\)的矩阵
\(A=rand\_matrix(matrix\_size=(h,h+x))\)
\(concat\)函数目的是将\(h_{t-1}\)与\(x_t\)拼接
\(h_t=\tanh(A·concat(h_{t-1},x_t))\)
即参数更新过程可视为以下函数:
\(h_t=func(h_{t-1},x_t)\)
函数公式:
\(tanh(x)=\frac{\sinh{x}}{\cosh{x}}=\frac{e^x-e^{-x}}{e^x+e^{-x}}\)
\(tanh\)函数的特点:
若没有\(\tanh\)函数会导致什么?
导致梯度消失或梯度爆炸,在不断地序列输入后最终状态向量会趋于0或区域无穷!
源论文:Hochreiter and Schmidhuber. Long short-term memory. Neural computation, 1997.
从结构图上的区别:
LSTM的几个重要部件:
结构图:
传输带做的事:过去的信息通过传输带送到下一个时刻。可以看到传输带上连接了几个朝上的箭头,因此其将几个组件组合起来运算
传输带的重要作用:通过传输带来避免梯度消失的问题
由总到分展开:
\(f=sigmoid(a)\)此处\(a\)为一个函数
\(output\_1=c\circ{f}\)(对位相乘)
\(Sigmoid\)函数:
特点:
结构图:
例如:
\(a\)可以拆解为如下:
\(a=W_f\cdot{concat(h_{t-1},x_t)}\)
其中\(W_f\)可以被学习
数学公式总和一起就是如下:
这一过程可以概括为一个函数:
\(output\_forget=func(h_{t-1},x_t,C_{t-1})\)
输入门\(i_t\)决定了传送带上哪个值会被更新

\(i_t=sigmoid(W_t\cdot{concat(h_{t-1},x_t)})\)
其中\(W_t\)可以被学习
结构图:
\(\widetilde{C_t}=\tanh({W_c\cdot{concat(h_{t-1},x_t)}})\)
其中\(W_c\)可以被学习
结构图:
\(C_t=f_t\circ{C_{t-1}}+i_t\circ{\widetilde{c_t}}\)
输出门\(o_t\)决定\(C_{t-1}\)流向\(h_t\)的信息
其中\(W_o\)可以被学习
\(o_t=sigmoid(W_o\cdot{concat(h_{t-1},x_t)})\)
\(h_t=o_t\circ\tanh(C_t)\)
\(h_t\)被拷贝成两份,一份成此轮LSTM的输出,另一份被传送到下一步
\(C_t\)中包含了遗忘和增加的信息,因此和输出门结合产生最终的状态向量
最终\(x_t\)向量的所有信息积累在\(h_t\)中
最后输出状态向量\(h_t\)后接上全连接层再做\(softmax\)输出最终的概率分布
LSTM有四个参数矩阵 \(W_f\),\(W_i\),\(W_c\),\(W_o\),参数矩阵经过激活函数后生成对应的“门”
在传送带\(C_{t-1}\)到\(C_t\)间,涉及了哪几个部分?
遗忘门
输入门
New Value值
从结构图中可以看出,\(C_{t-1}\)到\(C_t\)的更新过程中,涉及了几个输出\(h_{t-1}\),\(x_t\),\(C_{t-1}\),其中W矩阵有\(W_f\),\(W_i\),\(W_c\)
架构图:
特点:
第\(i(i\in{(0,n]})\)层的所有状态向量\(h_{ij}(j\in{[0,t]})\)输出后是第\(i+1\)层RNN的输入
人阅读是在脑子里积累阅读信息,RNN“阅读”则积累在状态向量\(h_t\)当中,而人类通常是从前往后阅读的习惯,但并不影响从后往前阅读来判断一个电影评论的情绪,因此双向RNN借助这种思想,悬链两条RNN,一条从前往后,另一条从后往前。
两条RNN不共享参数,各自输出其状态向量,然后将两条向量做\(concat\)操作记作向量\(y\)。
双向RNN为什么比单向的好?
RNN单向时会存在遗忘,即从左到右,容易遗忘左边的,反之也是
但实验表明,此处单向和双向RNN结果区别不大,原因如下:
解决方法:
预训练的流程:

此处为以字符级输入为例,输入若干字符,输出下一个字符的概率
具体例子如下:
再次将生成的输出字符t继续输入,下一预测可以为'.'则结束生成。
现有上面一段文字,策略是截取一段连续的字符序列\(charseq\)输入为\(x=charseq[:-1]\),输出为\(y=charseq[-1:]\),可以设定\(seg\_len=40\ stride=3\)
现在数据有了,生成问题可以理解为一个多分类问题
生成文本会根据输入的输出产生,如丢一本莎士比亚的书训练,会生成莎士比亚写作风格的文本,虽然可能不通顺或出现语法单词等错误。
准备好的数据就像以下这样:
因为英文字符的数量较少,因此直接构建字符字典{Token:Index}
然后将输入的字符使用one-hot编码
因为生成是有顺序的,因此LSTM用单向

问题:如果输出最后概率分布,如何选择下一个字符?
Option1:贪心选择,选最大概率分布的字符输出
next_index=np.argmax(pred)
Option2:多项式分布随机抽取
next_onehot=np.random.multinomial(1,pred,1)
next_index=np.argmax(next_onehot)
Option3:调整多项式分布
pred=pred**(1/temperature)
pred=pred/np.sum(pred)
作用结果,大的概率会变大,小的变小

减小temperature则会大的变的更大,小的变的更小
继续降低则会变的更极端,使得变成确定性
神经机器翻译需要用到Seq2Seq模型架构
本文做神经机器翻译的是英语和德语两个语言
例:
构建一个神经机器翻译的Seq2Seq模型,需要做一下工作:
包含翻译对的网站:http://www.manythings.org/anki/
一个英语句子如果可以match多个德语句子则正确
分词、构建操作时,分为字符级与单词级,由于两种语言的特性不同,分词的方式也不同,因此需要使用两种分词器,构建两种字典。
在构建词典时,对目标语言需要设置开始符号,和截止符,以在生成目标语言时开始和结束
One-Hot编码:
编码过程需要对英文和德语分别编码

One-Hot编码的图形表示:
每个字符用一个向量表示,每个句子用一个矩阵表示,矩阵为RNN的输入。
Encoder将输入的句子提取特征,丢弃,最终输出状态向量\(h\)和传输带\(c\)
Decoder用于生成目标翻译文本,Decoder的初始状态就是Encoder的最终状态。
不断重复训练过程,直到生成终止字符
后半部分相当于上一节的文本自动生成
Encoder使用BiLSTM(Encoder Only 文本生成器Decoder则不能)
使用Word-Level分词
多任务学习
英语-英语本身,Encoder只有一个,而训练数据多了一倍。即Encoder都是英语的,可以拿多个语言训练来更新Encoder
添加更多任务,添加更多Decoder生成各种语言,虽然德语的Decoder没有改进,但翻译的效果还是会变好
Attention(注意力机制,能够大大提升效果,在下一节!)
由于Seq2Seq有明显的缺陷,输入的句子很长的话会“记不住”句子,Encoder的最终状态会漏掉一些信息,则Decoder无从的到正确的句子,会缺少信息
Attention原论文:
Bahdanau, Cho, & Bengio. Neural machine translation by jointly learning to align and translate. In ICLR, 2015.
具有Attention的Seq2Seq模型:
Attention在Encoder结束后,和Decoder同步工作
权重\(a_i\)即为相关性\(a_1,a_2,...,a_m\),是\(\rm{h_1,h_2,...,h_m}\)与\(\rm{s_0}\)的相关性
$$
a_i=align(h_i,s_0)
$$
计算\(a_i\)有两种选择
Option1(使用的是原始paper的方法):
$$
\widetilde{a_i}=\rm{v}^\mit{T}\cdot{\tanh{\left[\begin{matrix}\rm{w}\cdot{concat(h_i,s_0)}\end{matrix} \right]}}
$$
其中$\rm{v^\mit{T}}$和$\rm{w}$是可训练的参数
2. 计算$a_i(i=1,...,m)$
Option2(更为常用,与Transformer相同)
此处以\(\rm{c_0}\)为例子,为\(\rm{a}\)与\(\rm{h}\)的加权平均
计算新的状态\(\rm{s_1}\)(注意此处加了和没加Attention的区别)
此处为一轮\(\rm{c}\)的计算
由此可以总结,因为\(a\)是关于\(\rm{h}\)和\(\rm{s_i}\)的函数,而\(\rm{c}\)是关于\(\rm{a}\)和\(\rm{h}\)的函数,因此可以视为\(\rm{c_i=f(h,s_i)}\)
则新状态计算公式为:\(\rm{s_i=g({x\prime}_i,s_{i-1},c_{i-1})}\)
持续更新\(\rm{c_i}\)
Attention总共有多少个参数呢?

颜色越深权重越大,每当Decoder生成新状态时,都会看一遍Encoder的所有状态,权重告诉Decoder应该关注的地方
Attention的论文
Self-Attention [2]: attention [1] beyond Seq2Seq models.
Attention不仅仅局限于Seq2Seq模型,实际上可以用于所有RNN架构上。此处使用RNN简化讲解:
初始时\(\rm{c_0}\)和\(\rm{h_0}\)都为全0向量
记\(current\)为当前最新轮次,以\(\rm{x}\)为例,最新输入为\(\rm{x_{current}}\)
\(\rm{h_{current}}\)如何计算?
传统的RNN更新\(h_{current}\)依赖于旧的状态\(\rm{h_{current-1}}\)和新的输入\(\rm{x_{current}}\),通过两者的拼接再计算。而自注意力机制则使用\(\rm{c_{current-1}}\)替代\(\rm{h_{current-1}}\),实际上将\(\rm{x_1}\),\(\rm{c_{current-1}}\)\(\rm{h_{current-1}}\)拼接也可以。由于初始状态\(\rm{h_0}\)为全零向量,因此此处加权平均可以忽略\(\rm{h_0}\)。
\(\rm{c_{current}}\)如何计算?
\(\rm{c_{current}}\)为\(\rm{h_0}\)到当前状态向量\(h_{current}\)与各自的权重\(a_{self}\)的加权平均
\({a_{current}}\)如何计算?
此处需要计算的是第\(current\)轮次的\(a\),即将最新的\(\rm{h_{current}}\)与其它的\(\rm{h}\)做\(\rm{align}\)计算各自的权重。
综上则可以总结:
计算\(\rm{c_1}\)为例子,因为\(\rm{h_0}\)为全零向量,又因为将\(\rm{h_1}\)做相关性计算,与自己就是1,因此\(\rm{c_1=h_1}\)。
王树森老师DeepLearning视频课件:
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport: