使用算法原理
㈠ LRU绠楁硶镄勫师鐞嗕笌瀹炵幇
LRU鏄疞east Recently Used镄勭缉鍐欙纴鍗虫渶杩戞渶灏戜娇鐢ㄧ畻娉曪纴搴旂敤闱㈤潪甯哥殑骞挎硾锛屾瘆濡俽edis褰扑腑镄勫唴瀛樻窐姹扮瓥鐣ャ傚洜涓鸿$畻链虹殑鍐呭瓨閮芥槸链夐檺镄勶纴褰撶敤鎴疯块梾镄勬暟鎹濡傛灉瀛桦湪鍐呭瓨褰扑腑鐩存帴杩斿洖镄勭粰鐢ㄦ埛镄勮瘽锛屾晥鐜囦细闱炲父蹇锛屼絾鏄濡傛灉鍐呭瓨涓嶅瓨鍦锛屽湪铡荤佺洏閲岄溃镆ユ垒镄勶纴鏁堢巼浼氩ぇ镓撴姌镓c傛墍浠ユ垜浠甯屾湜鍦ㄦ湁闄愮殑鍐呭瓨绌洪棿褰扑腑锛屽氩瓨鏀剧偣鐑镣规暟鎹锛岀敤鎴蜂笉缁忓父璁块梾镄勬暟鎹锛屽敖閲忔窐姹版帀锛岄伩鍏嶅崰鐢ㄥ唴瀛樼┖闂淬
浣跨敤鍙屽悜阈捐〃𨱒ュ疄鐜癓RU 杩欑瘒鏂囩珷宸茬粡鐢ㄥ弻钖戦摼琛ㄦ潵瀹炵幇杩尝RU绠楁硶浜嗭纴浣嗘槸锘轰簬鍙屽悜阈捐〃镄勭壒镐э纴浣垮缑璇ョ畻娉旷殑镞堕棿澶嶆潅搴︿负O(n)锛屾樉铹朵笉鏄链浼樼殑绠楁硶锛岄偅涔堟湁娌℃湁绠楁硶锛屽彲浠ヨ揪鍒疠(1)锛屽綋铹舵槸链夌殑锛屾棭镞╃殑璁$畻链虹戝﹀跺凡缁忔兂鍒帮纴骞朵笖宸茬粡瀹炵幇浜嗐
鍦ㄧ玛钥呬粙缁嶆帴涓嬫潵镄勫唴瀹规椂锛岃缮鏄甯屾湜鍏堜简瑙d竴涓嬩袱绡囧崥鏂囷细
涓銆 锲捐ВHashMap铡熺悊
浜屻 锲捐ВLinkedHashMap
涔嫔墠浣跨敤鍙屽悜阈捐〃铡诲疄鐜癓RU绠楁硶镞讹纴镞堕棿澶嶆潅搴︽病链夎揪鍒疠(1)锛屼富瑕佸师锲犲湪浜庨亶铡嗙粨镣规椂锛屽甫𨱒ョ殑镞堕棿寮阌锛岄偅涔堟崲鍙ヨ瘽璇达纴瑕佸疄鐜伴亶铡嗙粨镣规椂锛屾椂闂村嶆潅搴︿负O(1)锛岀涓镞堕棿𨱍冲埌镄勫簲璇ユ槸hash鏁扮粍锛屼絾鏄痟ash绠楁硶鍙鑳戒细瀛桦湪涓嶅悓镄刱ey鍊硷纴浜х敓鐩稿悓镄删ash鍊硷纴闾d箞鍙浠ュ皢涓嶅悓key锛屼絾鏄鐩稿悓hash鍊肩殑缁撶偣锛屼互鍗曢摼琛ㄧ殑褰㈠纺瀛樻斁銆傝繖镙蜂粎浠呮槸瀹炵幇浜嗗瓨鍙栨椂闂村嶆潅搴︿负O(1)锛屽备綍瀹炵幇鏁版嵁鑳藉熸寜璁块梾椤哄簭瀛樻斁锻锛熷苟涓斿炲垹镄勬椂闂村嶆潅搴︿负O(1)锛岃繖涓鍙浠ヤ娇鐢ㄥ弻钖戦摼琛ㄦ潵瀹炵幇锛屾墍浠ョ患钖堟潵璁诧纴灏辨槸瀹炵幇鏁e垪鏁扮粍+鍙屽悜阈捐〃𨱒ヤ娇鐢↙RU锛屽彲浠ヨ揪鍒版椂闂村嶆潅搴︿负O(1)銆
阃昏緫瑙嗗浘濡备笅:
鍜嬩竴鐪嬭繖涓锲句贡镄勫緢锛岀◢寰瑙i喷涓涓嬶纴濡傛灉镒熻夌悊瑙d笂链夌偣锲伴毦锛屽彲浠ュ厛铡讳简瑙d竴涓嬩箣鍓嶆帹钻愮殑涓ょ瘒鍗氭枃锛岄偅閲屼细浠嬬粛镄勬洿锷犺︾粏涓镣广
1.链宸︿晶鍏跺疄灏辨槸涓涓鏅阃氱殑鏁扮粍锛屾暟缁勭殑澶у皬蹇呴’鏄2镄勫嶆暟锛岃繖涓铡熷洜鏄浠涔埚憿锛熷洜涓鸿繖涓鏁扮粍镄勫瓨鏀炬柟寮忔槸鏁e垪镄勶纴镒忔濆氨鏄闇瑕乲ey.hashcode & (length -1)镓嶈兘寰楀嚭瀛樻斁浣岖疆镄勬柟寮忥纴hash镄勫ソ澶勬槸鍙浠ユ牴鎹甼ey鍊硷纴鍦ㄦ椂闂村嶆潅搴︿负O(1)镄勫墠鎻愭垒鍒板瑰簲镄勫瓨鏀句綅缃锛岃繖涔熸槸鎴戜滑镄勫埯琛凤纴璇村埌杩欓噷鍏跺疄杩樻病链夎В閲娄负浠涔堜竴瀹氲佹槸2镄勫嶆暟锛屽洜涓2镄勫嶆暟-1锛岃繖涓鏁扮殑浜岃繘鍒讹纴涓瀹氩叏鏄1锛屾瘆濡16-1=15锛屼簩杩涘埗琛ㄧず灏辨槸1111锛&杩愮畻绗﹀叾瀹炲氨鏄灏嗗煎叏閮ㄥ寲鎴愪簩杩涘埗阃愪綅涓庯纴姣斿10111011 & 1111 = 1011 = 11锛屼絾鏄濡傛灉涓嶆槸2镄勫嶆暟锛屾瘆濡7-1=6锛屽寲鎴愪簩杩涘埗灏辨槸0110锛岀敱浜庢汤浣嶆槸0锛屼笉绠′粈涔堜簩杩涘埗鍊间笌0110锅&杩愮畻锛屼竴瀹氭槸锅舵暟锛岃繖镙蜂细瀵艰嚧鏁e垪鍒嗗竷涓嶅潎鍖銆
2.涓嶅悓key鍊硷纴鐩稿悓hash鍊硷纴濡备綍瀛樻斁锻锛熺浉钖岀殑hash鍊煎仛涓庤繍绠椾竴瀹氲兘澶熷缑鍒扮浉钖岀殑鏁扮粍鑴氭爣锛岃繖浜涚粨镣癸纴浠ュ崟阈捐〃镄勫舰寮忓瓨鍦锛屽氨鏄锲句腑鏁扮粍鍙充晶镄勫崟阈捐〃銆
3.濡备綍瀹炵幇鎸夎块梾椤哄簭锛熶笂锲鹃櫎铡绘暟缁勫拰鎸傚湪鏁扮粍鍙充晶镄勫崟阈捐〃锛岃缮链夌豢镩插拰榛勮壊镄勫崟钖戠澶达纴鍦ㄥ彸涓婅掕缮链変竴涓鍙屽悜阈捐〃镄勫ご鎸囬拡銆傚叾瀹炶繖浜涚澶村氨鏄缁存姢涓嶅悓缁撶偣镄勮块梾椤哄簭锛屽嵆鍙屽悜阈捐〃銆
镐讳笂镓杩帮纴杩欑嶆暟鎹缁撴瀯瀹氢箟镄勭粨鏋勪綋濡备笅锛
class Node{
Object key; //瀛樻斁key鍊硷纴鐢ㄤ簬璁$畻瀛樻斁鏁扮粍鑴氭爣浣岖疆
Object value;//瀛樻斁鍏幂礌鍊
int hash;//瀛樻斁key.hashcode
Node next;//缁存姢鍗曢摼琛ㄩ‘搴
Node before;//缁存姢鍙屽悜阈捐〃椤哄簭
Node after;
}
绗旇呯敤java瀹炵幇濡备笅锛屾劅鍏磋叮鍙浠ョ敤镊宸卞枩娆㈢殑璇瑷铡诲疄鐜颁竴阆嶏纴锷犳繁鐞呜В锛
鍏跺疄浠ヤ笂瀹炵幇搴曞眰铡熺悊灏辨槸LinkedHashMap镄勫疄鐜板师鐞嗭纴鍙涓嶈繃绗旇呭仛浜嗕竴浜涚亩鍖栵纴铡绘帀浜嗙箒鐞愮殑缁ф圹锛屾墿瀹圭瓑锛岀獊鍑轰简绠楁硶镙稿绩锛屽傛灉璇昏呮劅鍏磋叮涔熷彲浠ュ幓镰旂┒涓涓婰inkedHashMap镄勬簮镰併
浣跨敤LinkedHashMap𨱒ュ疄鐜癓RU绠楁硶锛
鐪嬭捣𨱒ユ槸涓嶆槸绠鍗曚简寰埚氾纴锲犱负LinkedHashMap搴曞眰宸茬粡灏佽呭ソ浜嗭纴鎴戜滑鐩存帴璋幂敤灏卞ソ锛屼絾鏄浣滀负涓涓𨱍宠佸彉浼樼镄勭爜鍐滐纴涓瀹氲佺煡鍏剁劧鐭ュ叾镓浠ョ劧銆
浣跨敤鏁e垪+鍙屽悜阈捐〃镄勬柟寮忔槸濡备綍瀹炵幇O(1)澶嶆潅搴︾殑锛熷湪瀹炵幇LRU绠楁硶杩囩▼涓锛屾棤闱炰袱绉嶆搷浣滐纴镆ユ垒鍜屼慨鏀癸纴浣跨敤鏁e垪鏁扮粍瀹炵幇镆ユ垒镞堕棿澶嶆潅搴︿负O(1)锛屼娇鐢ㄥ弻钖戦摼琛ㄥ疄鐜颁慨鏀瑰嶆潅搴︿负O(1)锛屽苟涓斿弻钖戦摼琛ㄨ缮鍙浠ョ淮鎶よ块梾椤哄簭锛屾墍浠ヤ娇鐢ㄨ繖绉嶆柟寮忥纴鍙浠ヨ揪鍒疠(1)銆
㈡ 古典密码学常用的技术和主要的密码算法原理
古典密码技术根据其基本原理大体可以分为两类:替换密码技术和换位密码技术。
古典密码是密码学中的其中一个类型,其大部分加密方式都是利用替换式密码或移项式密码,有时则是两者的混合。其于历史中经常使用,但在现代由于计算机的出现,使得古典密码解密已经不再困难,已经很少使用,大部分的已经不再使用了。
利用一个密钥字来构造替换作为密钥,先将密钥字作为首段密文,然后将之后未在字母表中出现过的字母依次写在此密钥字之后,构造出一个字母替换表。当密文为英文单词时,最多可以有26!个不同的替换表(包括恒等变换)。
仿射密码技术:
即结合乘法密码技术和移位密码技术。
它的加密函数是 e(x)=ax+b,其中a和 m互质,m是字母的数目。
解码函数是 d(x)=i*(x-b)mod m,其中 i 是 a 的乘法逆元。
当a=0时,仿射密码技术退化为移位替换密码技术。
当b=0时,仿射密码技术退化为乘法密码技术。
㈢ 一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)
反向传播算法(Backpropagation Algorithm,简称BP算法)是深度学习的重要思想基础,对于初学者来说也是必须要掌握的基础知识!本文希望以一个清晰的脉络和详细的说明,来让读者彻底明白BP算法的原理和计算过程。
全文分为上下两篇,上篇主要介绍BP算法的原理(即公式的推导),介绍完原理之后,我们会将一些具体的数据带入一个简单的三层神经网络中,去完整的体验一遍BP算法的计算过程;下篇是一个项目实战,我们将带着读者一起亲手实现一个BP神经网络(不使用任何第三方的深度学习框架)来解决一个具体的问题。
图 1 所示是一个简单的三层(两个隐藏层,一个输出层)神经网络结构,假设我们使用这个神经网络来解决二分类问题,我们给这个网络一个输入样本 ,通过前向运算得到输出 。输出值 的值域为 ,例如 的值越接近0,代表该样本是"0"类的可能性越大,反之是"1"类的可能性大。
为了便于理解后续的内容,我们需要先搞清楚前向传播的计算过程,以图1所示的内容为例:
输入的样本为:
第一层网络的参数为:
第二层网络的参数为:
第三层网络的参数为:
第一层隐藏层有三个神经元: 、 和 。该层的输入为:
以 神经元为例,则其输入为:
同理有:
假设我们选择函数 作为该层的激活函数(图1中的激活函数都标了一个下标,一般情况下,同一层的激活函数都是一样的,不同层可以选择不同的激活函数),那么该层的输出为: 、 和 。
第二层隐藏层有两个神经元: 和 。该层的输入为:
即第二层的输入是第一层的输出乘以第二层的权重,再加上第二层的偏置。因此得到和的输入分别为:
该层的输出分别为: 和 。
输出层只有一个神经元 :。该层的输入为:
即:
因为该网络要解决的是一个二分类问题,所以输出层的激活函数也可以使用一个Sigmoid型函数,神经网络最后的输出为: 。
在1.1节里,我们已经了解了数据沿着神经网络前向传播的过程,这一节我们来介绍更重要的反向传播的计算过程。假设我们使用随机梯度下降的方式来学习神经网络的参数,损失函数定义为 ,其中 是该样本的真实类标。使用梯度下降进行参数的学习,我们必须计算出损失函数关于神经网络中各层参数(权重 和偏置 )的偏导数。
假设我们要对第 层隐藏层的参数 和 求偏导数,即求 和 。假设 代表第 层神经元的输入,即 ,其中 为前一层神经元的输出,则根据链式法则有:
因此,我们只需要计算偏导数 、 和 。
前面说过,第k层神经元的输入为: ,因此可以得到:
上式中, 代表第 层神经元的权重矩阵 的第 行, 代表第 层神经元的权重矩阵 的第 行中的第 列。
我们以1.1节中的简单神经网络为例,假设我们要计算第一层隐藏层的神经元关于权重矩阵的导数,则有:
因为偏置b是一个常数项,因此偏导数的计算也很简单:
依然以第一层隐藏层的神经元为例,则有:
偏导数 又称为 误差项(error term,也称为“灵敏度”) ,一般用 表示,例如 是第一层神经元的误差项,其值的大小代表了第一层神经元对于最终总误差的影响大小。
根据第一节的前向计算,我们知道第 层的输入与第 层的输出之间的关系为:
又因为 ,根据链式法则,我们可以得到 为:
由上式我们可以看到,第 层神经元的误差项 是由第 层的误差项乘以第 层的权重,再乘以第 层激活函数的导数(梯度)得到的。这就是误差的反向传播。
现在我们已经计算出了偏导数 、 和 ,则 和 可分别表示为:
下面是基于随机梯度下降更新参数的反向传播算法:
单纯的公式推导看起来有些枯燥,下面我们将实际的数据带入图1所示的神经网络中,完整的计算一遍。
我们依然使用如图5所示的简单的神经网络,其中所有参数的初始值如下:
输入的样本为(假设其真实类标为"1"):
第一层网络的参数为:
第二层网络的参数为:
第三层网络的参数为:
假设所有的激活函数均为Logistic函数: 。使用均方误差函数作为损失函数:
为了方便求导,我们将损失函数简化为:
我们首先初始化神经网络的参数,计算第一层神经元:
上图中我们计算出了第一层隐藏层的第一个神经元的输入 和输出 ,同理可以计算第二个和第三个神经元的输入和输出:
接下来是第二层隐藏层的计算,首先我们计算第二层的第一个神经元的输入z₄和输出f₄(z₄):
同样方法可以计算该层的第二个神经元的输入 和输出 :
最后计算输出层的输入 和输出 :
首先计算输出层的误差项 ,我们的误差函数为 ,由于该样本的类标为“1”,而预测值为 ,因此误差为 ,输出层的误差项为:
接着计算第二层隐藏层的误差项,根据误差项的计算公式有:
最后是计算第一层隐藏层的误差项:
㈣ 深入浅出BP神经网络算法的原理
深入浅出BP神经网络算法的原理
相信每位刚接触神经网络的时候都会先碰到BP算法的问题,如何形象快速地理解BP神经网络就是我们学习的高级乐趣了(画外音:乐趣?你在跟我谈乐趣?)
本篇博文就是要简单粗暴地帮助各位童鞋快速入门采取BP算法的神经网络。
BP神经网络是怎样的一种定义?看这句话:一种按“误差逆传播算法训练”的多层前馈网络。
BP的思想就是:利用输出后的误差来估计输出层前一层的误差,再用这层误差来估计更前一层误差,如此获取所有各层误差估计。这里的误差估计可以理解为某种偏导数,我们就是根据这种偏导数来调整各层的连接权值,再用调整后的连接权值重新计算输出误差。直到输出的误差达到符合的要求或者迭代次数溢出设定值。
说来说去,“误差”这个词说的很多嘛,说明这个算法是不是跟误差有很大的关系?
没错,BP的传播对象就是“误差”,传播目的就是得到所有层的估计误差。
它的学习规则是:使用最速下降法,通过反向传播(就是一层一层往前传)不断调整网络的权值和阈值,最后使全局误差系数最小。
它的学习本质就是:对各连接权值的动态调整。
拓扑结构如上图:输入层(input),隐藏层(hide layer),输出层(output)
BP网络的优势就是能学习和储存大量的输入输出的关系,而不用事先指出这种数学关系。那么它是如何学习的?
BP利用处处可导的激活函数来描述该层输入与该层输出的关系,常用S型函数δ来当作激活函数。
我们现在开始有监督的BP神经网络学习算法:
1、正向传播得到输出层误差e
=>输入层输入样本=>各隐藏层=>输出层
2、判断是否反向传播
=>若输出层误差与期望不符=>反向传播
3、误差反向传播
=>误差在各层显示=>修正各层单元的权值,直到误差减少到可接受程度。
算法阐述起来比较简单,接下来通过数学公式来认识BP的真实面目。
假设我们的网络结构是一个含有N个神经元的输入层,含有P个神经元的隐层,含有Q个神经元的输出层。
这些变量分别如下:
认识好以上变量后,开始计算:
一、用(-1,1)内的随机数初始化误差函数,并设定精度ε,最多迭代次数M
二、随机选取第k个输入样本及对应的期望输出
重复以下步骤至误差达到要求:
三、计算隐含层各神经元的输入和输出
四、计算误差函数e对输出层各神经元的偏导数,根据输出层期望输出和实际输出以及输出层输入等参数计算。
五、计算误差函数对隐藏层各神经元的偏导数,根据后一层(这里即输出层)的灵敏度(稍后介绍灵敏度)δo(k),后一层连接权值w,以及该层的输入值等参数计算
六、利用第四步中的偏导数来修正输出层连接权值
七、利用第五步中的偏导数来修正隐藏层连接权值
八、计算全局误差(m个样本,q个类别)
比较具体的计算方法介绍好了,接下来用比较简洁的数学公式来大致地概括这个过程,相信看完上述的详细步骤都会有些了解和领悟。
假设我们的神经网络是这样的,此时有两个隐藏层。
我们先来理解灵敏度是什么?
看下面一个公式:
这个公式是误差对b的一个偏导数,这个b是怎么?它是一个基,灵敏度δ就是误差对基的变化率,也就是导数。
因为?u/?b=1,所以?E/?b=?E/?u=δ,也就是说bias基的灵敏度?E/?b=δ等于误差E对一个节点全部输入u的导数?E/?u。
也可以认为这里的灵敏度等于误差E对该层输入的导数,注意了,这里的输入是上图U级别的输入,即已经完成层与层权值计算后的输入。
每一个隐藏层第l层的灵敏度为:
这里的“?”表示每个元素相乘,不懂的可与上面详细公式对比理解
而输出层的灵敏度计算方法不同,为:
而最后的修正权值为灵敏度乘以该层的输入值,注意了,这里的输入可是未曾乘以权值的输入,即上图的Xi级别。
对于每一个权值(W)ij都有一个特定的学习率ηIj,由算法学习完成。