机器学习读书笔记:强化学习
文章目录
- 强化学习基本模型
- K-摇臂赌博机模型
- ϵ\epsilonϵ-贪心
- Softmax
- 有模型学习
- 策略评估
- 策略改进
- 免模型学习
- 蒙特卡洛强化学习
- 采样
- 策略改进
- 时态差分学习
- 值函数近似
- 模仿学习
- 直接模仿学习
- 逆强化学习
强化学习基本模型
强化学习的过程如下图所示:
相当于系统会与外界环境有不停的互动,先执行不同的动作,再根据外界环境的响应来判断这个动作的好坏。最终学会在什么环境下执行什么动作。这个和我们人在日常的学习过程中非常类似,有点胡萝卜加大棒的意思。
在这个简单的模型中,有几个概念:
- 环境EEE
- 机器有一个状态空间XXX,状态空间包括了多个状态,机器可以在状态之间进行切换。
- 机器同时还有一个动作空间AAA,动作空间包括了多个动作,在不同的状态可以执行不同的动作。
- 机器执行动作之后,环境会根据状态变化、动作等因素给出一个奖赏RRR,奖赏可能是正,可能是负。我理解是要进行了状态的转换才会有奖赏,当然这里的转换可以是自身到自身的转换。也就是xi−>xj,i=jx_i->x_j, i=jxi−>xj,i=j
- 还有一个就是执行某个动作之后,机器从状态xix_ixi转换到xjx_jxj的概率PPP。
- 上面的四元组<X,A,R,P><X,A,R,P><X,A,R,P>就可以描述一个基本的强化模型。
- 状态间切换是一个马尔科夫决策过程,简单的说就是状态的变换只依赖于当前的状态,不依赖历史状态。
书中给出了一个西瓜浇水的马尔科夫决策过程图:
强化学习的目标就是根据这个四元组模型确定一个策略:π(x,a)\pi(x,a)π(x,a),也就是在哪个环境下就执行哪个动作的策略。或者用概率论的说法是,在xxx状态下,选择动作aaa的概率。
强化学习获得策略是要获得累积奖赏,就是整个过程中的最大奖赏,这个就是个贪心或者动态规划的问题了。有可能当前状态的某个动作aia_iai奖赏稍高,下一步就没有奖赏了;而动作aja_jaj奖赏稍低,下一步就是高奖赏。针对这个奖赏的计算,书中提到了两种方式:
- T步累积奖赏:由公式E[1T∑t=1Trt]E[\frac{1}{T}\sum_{t=1}^Tr_t]E[T1∑t=1Trt]来计算。就是计算T步总的奖赏值,优化目标是让这个奖赏值最大。
- γ\gammaγ折扣累积奖赏:由公式E[∑t=0∞γtrt+1]E[\sum_{t=0}^{\infty}{\gamma^tr_{t+1}}]E[∑t=0∞γtrt+1]。以一个小于1的折扣γ\gammaγ是的之前的策略权重进行打折。
强化学习可以看做是一个引入了外界环境给出标签的一个监督学习的过程。
K-摇臂赌博机模型
如果每个动作都可以是一个确定的奖赏,那么最大化奖赏就比较简单了,因为默认这是一个马尔科夫决策过程,每个步骤选最大就行了。但是,实际情况往往不是这样,比如上图中,在缺水状态下浇水不一定就能获得奖赏,里面有一个概率在里面。
而K-摇臂赌博机模型如图:
我的理解如下:
- 动作空间是确定的,有5个选择。
- 每个动作对应的状态切换是不一定的,也就是这个PPP不确定。
- 我理解奖赏是确定的,每个摇臂会出多少钱应该是写了的。
- 状态空间应该就是一个,在这个模型中不太重要。
这里矛盾的地方就在于,总感觉下一次摇臂就会出奖了,而手里的币是有限的,下一个币到底是投哪一个。这里存在有两种策略:
- 仅探索:也就是将所有的机会平均分配给每个摇臂,有100个币,每个摇臂投20。最优以每个摇臂各自的平均吐币概率作为其奖赏期望的估计。
- 仅利用:按下目前最优的,比如已经投了10个币,而当前吐币概率最高的是3,那么第11个就摇3号摇臂。如果这次没出,3号的概率就降低了,此时2号最高,那么第12个就摇2号摇臂,直到投入所有的硬币。最后计算所有的奖赏。
实际上,仅利用一个策略是不够的,必须利用某种方式综合利用这两种策略。
ϵ\epsilonϵ-贪心
简单的说,每次有ϵ\epsilonϵ的概率进行探索;以1−ϵ1-\epsilon1−ϵ的概率进行利用。
令Q(k)Q(k)Q(k)表示摇臂kkk的平均奖赏。若摇臂kkk被尝试了nnn次,那么
Q(k)=1n∑i=1nviQ(k)=\frac{1}{n}\sum_{i=1}^n{v_i} Q(k)=n1i=1∑nvi
这里需要记录所有的奖赏值。可以改进为:
Qn(k)=Qn−1(k)+1n(vn−Qn−1(k))Q_n(k)=Q_{n-1}(k)+\frac{1}{n}(v_n-Q_{n-1}(k)) Qn(k)=Qn−1(k)+n1(vn−Qn−1(k))
这样,对每个摇臂只需要记录两个值,累积的平均值和当前的值就足够了。
贪心算法的流程:
在这个过程中,每次机会都分成了ϵ\epsilonϵ和1−ϵ1-\epsilon1−ϵ去利用不同策略进行摇臂。
其实,我觉得最简单的理解就是100个币,而ϵ=0.2\epsilon=0.2ϵ=0.2,那么就是20个币用做探索,每个摇臂分4个。而剩下的80个按照仅利用的策略去摇。
Softmax
Softmax算法基于当前一直的摇臂平均奖赏来对探索和利用两种策略进行折中。在这个算法中,每次投币的摇臂号使用下面的概率公式来计算:
P(k)=eQ(k)τ∑i=1KeQ(k)τP(k) = \frac{e^{\frac{Q(k)}{\tau}}}{\sum_{i=1}^K{e^{\frac{Q(k)}{\tau}}}} P(k)=∑i=1KeτQ(k)eτQ(k)
这个公式是对每个摇臂根据以往的奖赏计算概率,哪个摇臂算出来的值大,就选哪个。也就是P(3)P(3)P(3)最大,这次的币就给3号摇臂。
- 如果τ\tauτ接近于0,Softmax将近似于仅利用的策略。我理解是因为分子项基本就是由Q(k)Q(k)Q(k)来确定,哪个Q(k)Q(k)Q(k)大,就会选哪个。
- 如果τ\tauτ接近于无限大,Softmax将近似于仅探索的策略。分子接近于1,下面是各个摇臂的求和,如果K=5K=5K=5,分母项就是5,就是平均概率了。
算法过程如下:
有模型学习
在上面的K-摇臂模型中,强化学习模型四元组中的PPP是不确定的。如果考虑四元组全部已知,将这样的情况称之为有模型学习。有了模型后,当然就是确定策略了,在确定策略的过程中,一般有两个场景。
策略评估
假设基于已知的模型<X,A,P,R><X,A,P,R><X,A,P,R>,已经有了策略π\piπ,需要计算这个策略的累积奖赏。根据上面提到过的两种奖赏定义:T步累积奖赏和γ\gammaγ折扣累积奖赏,再根据已知的模型四元组,可以进行递归的推导(还有一个因素是因为这个过程是一个马尔科夫过程)。
对于奖赏值函数VTπxV_T^{\pi}{x}VTπx,表示策略π\piπ从状态xxx出发所带来的累积奖赏,可以根据递归公式(公式1,后续会用到):
VTπx=∑a∈Aπ(x,a)∑x′∈XPx−>x′a(1TRx−>x′a+T−1TVT−1π(x′))V_T^{\pi}{x}=\sum_{a\in A}{\pi(x,a)}\sum_{x^{\prime}\in X}{P_{x->x^{\prime}}^a(\frac{1}{T}R_{x->x^{\prime}}^a+\frac{T-1}{T}V_{T-1}^{\pi}(x^{\prime}))} VTπx=a∈A∑π(x,a)x′∈X∑Px−>x′a(T1Rx−>x′a+TT−1VT−1π(x′))
将VT−1π(x′)V_{T-1}^{\pi}(x^{\prime})VT−1π(x′)继续可以展开,因为所有的值都是已知,因此可以计算出每一步的奖赏,从而来评估这个策略。
γ\gammaγ累积奖赏同样可以通过递归公式进行计算:
Vγπx=∑a∈Aπ(x,a)∑x′∈XPx−>x′a(Rx−>x′a+γVT−1π(x′))V_{\gamma}^{\pi}{x}=\sum_{a\in A}{\pi(x,a)}\sum_{x^{\prime}\in X}{P_{x->x^{\prime}}^a(R_{x->x^{\prime}}^a+\gamma V_{T-1}^{\pi}(x^{\prime}))} Vγπx=a∈A∑π(x,a)x′∈X∑Px−>x′a(Rx−>x′a+γVT−1π(x′))
通过递归公式最终递归到最初的状态x0x_0x0,只要确定好这个最初的状态就行了。
如果是使用γ\gammaγ折扣累积奖赏,把第3行的代码替换掉就可以了。还有就是停止条件一般会改成maxx∈X∣V(x)−V′(x)∣<θ\max_{x\in X}|V(x)-V^{\prime}(x)| < \thetamaxx∈X∣V(x)−V′(x)∣<θ,也就是两次迭代的差值小于某个阈值就停止。
评估多个策略,就可以根据每个策略的累积奖赏值来进行评估了。
策略改进
如果评估后,想改进这个策略,那就是另外一种应用场景了。实际上就是想找到一个策略,让这个确定了四元组的模型在这个策略上达到最大的奖赏,也就是Vπ(x)V^{\pi}(x)Vπ(x)最大:
π∗=argπmax∑x∈XVπ(x)\pi^*=\arg_{\pi}max\sum_{x\in X}V^{\pi}(x) π∗=argπmaxx∈X∑Vπ(x)
也就是可以获得最大值函数的那个策略就是最优策略。在上面的公式1中,V(x)V(x)V(x)是计算从xxx出发的所有动作进行求和,这里改一下就成了求最大值:
VTπx=maxa∈A∑x′∈XPx−>x′a(1TRx−>x′a+T−1TVT−1π(x′))V_T^{\pi}{x}=max_{a\in A}\sum_{x^{\prime}\in X}{P_{x->x^{\prime}}^a(\frac{1}{T}R_{x->x^{\prime}}^a+\frac{T-1}{T}V_{T-1}^{\pi}(x^{\prime}))} VTπx=maxa∈Ax′∈X∑Px−>x′a(T1Rx−>x′a+TT−1VT−1π(x′))
定义一个Q(x,a)Q(x,a)Q(x,a)表示在xxx状态下通过动作aaa能达到的奖赏函数,上面的公式就可以写成,称作Bellman等式:
VTπx=maxa∈AQπ∗(x,a)V_T^{\pi}{x}=max_{a\in A}Q^{\pi^*}(x,a) VTπx=maxa∈AQπ∗(x,a)
上面是一个不等式的推导,从不等式中可以看出对某个策略π\piπ的改进方法,从中挑选一个动作aaa,将其改成a′a^{\prime}a′,变更的条件就是Q(x,a′)>Q(x,a)Q(x,a^{\prime})>Q(x,a)Q(x,a′)>Q(x,a)。更改后得到策略π′\pi^{\prime}π′,从而也有了值函数V′(x)V^{\prime}(x)V′(x),一直修改策略中的动作,直到V(x)=V′(x)V(x)=V^{\prime}(x)V(x)=V′(x),这是的π′\pi^{\prime}π′就是最优的策略。
综合上面的策略评估和改进策略,就可以迭代生成到最优的策略,先初始化以一个策略,然后评估,如果不是最优,就改进,不停的迭代直到生成最优的策略:
这个方法被称为策略迭代。
策略迭代中,每次生成一个策略,都需要进行策略评估,比较费事,可以直接用值函数进行评估:
免模型学习
在真实场景中,模型的四元组不太可能全都知道,比如上面的K-摇臂模型就是。更何况还有更复杂的场景。我们只需要知道做了某个动作,有一些什么奖赏,去不停的尝试,和监督学习类似,视图去估计这样的一个模型,来确定策略。这样的学习方式称作免模型学习。
在这种情况下:
对策略无法做评估
因为不知道到底有多少动作可选,V(x)V(x)V(x)无法计算,只能使用Q(x,a)Q(x,a)Q(x,a)来评估。
蒙特卡洛强化学习
采样
蒙特卡洛强化学习是基于采样的学习方法。对整个系统进行多次采样,在K-摇臂中就是投币,每次采样投100个币,共投5次,算作有5次采样。对每次的采样进行记录:
<x0,a0,r1,x1,a1,r2,…,xT−1,aT−1,rT><x_0,a_0,r_1,x_1,a_1,r_2,\dots,x_{T-1},a_{T-1},r_T> <x0,a0,r1,x1,a1,r2,…,xT−1,aT−1,rT>
对每次的采样中的状态-动作键值对所对应的奖赏进行平均,比如键值对<x0,a0><x_0,a_0><x0,a0>的奖赏是r1r_1r1,平均之后就可以得到状态-动作值函数Q(x0,a0)Q(x_0,a_0)Q(x0,a0)的平均值,从而得到T步中每一步的QQQ值。
在采样的过程中,如果策略是确定性的,多次采样可能是得到相同或者非常类似的轨迹,这对估计整个模型是不利的,因此,还需要想办法得到多条轨迹,但是策略本身是不能变的,策略变了,评估就没有意义了。
采样的贪心ϵ\epsilonϵ策略:借用K-摇臂中的贪心策略,而贪心策略是指以ϵ\epsilonϵ的概率是从所有动作中随机选取一个;以1−ϵ1-\epsilon1−ϵ的概率选取最优的动作。这样,每个不在原始策略中的动作的样本出现的概率也会有ϵ∣A∣\frac{\epsilon}{|A|}∣A∣ϵ,从而得到不同的轨迹,也不会大概率的改变平均值。
策略改进
增加了贪心策略的采样不影响上面提到的Bellman等式,所以改进方法不变,整个的蒙特卡洛学习方法流程如下:
- 评估和改进都是同一个策略,成为“同策略”算法
- 每得到一个样本,进行增量的更新,贪心策略也是增量的。
从上面的过程可以看出来,策略更新的时候也是使用了贪心算法的,有一定的概率选的不是最好的动作,导致最终效果会没那么好。而我们引入贪心只是为了增加轨迹的多样性,并不是要在改进的时候使用。因此有了下面的改进:
这里面主要就是增加了一个pipipi的部分。这部分就是改进点,我们使用贪心算法选择了不同的轨迹,那么两条不同的轨迹可以看成是两个不同的策略生成的:一个是我们需要评估和优化的策略π\piπ,一个是基于贪心策略修改了动作的策略π′\pi^{\prime}π′。
那么,策略π\piπ生成这个轨迹的概率是PπP^{\pi}Pπ,策略π′\pi^{\prime}π′生成这个轨迹的概率是Pπ′P^{\pi^{\prime}}Pπ′。然后一段看得不明白过程但是不太明白为什么这么证明的证明过程证明了我们只需要一个比值:
PπPπ′\frac{P^{\pi}}{P^{\pi^{\prime}}} Pπ′Pπ
其中,根据策略出来的概率Pπ=1P^{\pi} = 1Pπ=1,而Pπ′P^{\pi^{\prime}}Pπ′为贪心策略里面的那两个值,也就是成了这个算法中的最要改进点。
这样的算法过程称作异策略算法,因为评估和改进的策略不是同一个。
时态差分学习
这个算法是针对上面的蒙特卡洛方法进行改进的。在蒙特卡洛方法中,每次都要对Q进行求和平均计算,还有奖赏的计算。这个方法参考之前K-摇臂章节中提到的增量更新方法,将蒙特卡洛方法过程中的第4-8步进行优化。
使用公式:
Qt+1pi(x,a)=Qtpi(x,a)+1t+1(rt+1−Qtpi(x,a))Q_{t+1}^{pi}(x,a)=Q_{t}^{pi}(x,a)+\frac{1}{t+1}(r_{t+1}-Q_{t}^{pi}(x,a)) Qt+1pi(x,a)=Qtpi(x,a)+t+11(rt+1−Qtpi(x,a))
也就是每次只需要保留ttt时刻的状态-动作方法QtQ_tQt,还有得到t+1t+1t+1时刻的奖赏rrr即可。
后面的一段话描述,当天没看懂,过个周末来看,貌似看明白了,果然还是要休息一下。
上面这个公式可以理解为ttt时刻的函数QtQ_tQt,加一个增量项的结果。后面的一截就是增量项,而1t+1\frac{1}{t+1}t+11为这个增量项的权重,这里是做的平均。所以把这个换成一个系数α\alphaα,代表每次增量的权重:αt+1(rt+1−Qtpi(x,a))\alpha_{t+1}(r_{t+1}-Q_t^{pi}(x,a))αt+1(rt+1−Qtpi(x,a))。α\alphaα为学习率,如果针对每个QtQ_tQt进行展开,所有的系数之和会为1,我理解是α+α2+⋯+αt\alpha+\alpha^2+\dots+\alpha^tα+α2+⋯+αt,因为α\alphaα是小于1的正数,为什么等于0不太清楚。
书中给出了γ\gammaγ折扣奖赏在上一公式上的推导,也就是把上面公式中的rt+1r_{t+1}rt+1改成了γ\gammaγ奖赏的计算方式:
Qt+1π(x,a)=Qtπ(x,a)+α(Rx−>x′a+γQtπ(x′,a′)−Qtπ(x,a))Q_{t+1}^{\pi}(x,a)=Q_{t}^{\pi}(x,a)+\alpha(R_{x->x^{\prime}}^a+\gamma Q_{t}^{\pi}(x^{\prime},a^{\prime})-Q_{t}^{\pi}(x,a)) Qt+1π(x,a)=Qtπ(x,a)+α(Rx−>x′a+γQtπ(x′,a′)−Qtπ(x,a))
每到一个新的时刻,就使用这个公式进行计算。这个公式只需要
- 前一步的状态xxx,state
- 前一步的动作aaa, action
- 奖赏Rx−>x′aR_{x->x^{\prime}}^aRx−>x′a, reward
- 当前状态x′x^{\prime}x′, state
- 下一步动作a′a^{\prime}a′, action
通过选择最大的QQQ来更新策略,这就是Sarsa算法(上面五个要素的首字母)。
如果选择和更新是基于不同的策略,和上面的蒙特卡洛一样,就是“异策略”算法Q−Q-Q−学习算法:
值函数近似
之前的强化学习模型中的XXX,也就是状态空间都是按照离散值来的,如果XXX是一个连续值,该怎么生成策略呢?第一想法就是做离散化,但是问题在于很多情况下的XXX定义域是不清楚的,没法准确的做离散化。
也就是说,在Sarsa算法中,Q(x,a)Q(x,a)Q(x,a)没法进行计算和表示。因为在有限离散值中,函数Q是和x,ax,ax,a的一个表格函数,想象成一个xxx行, aaa列的表格,行列定了,Q就定了。而此时xxx是一个连续值,除非定义了一个明确的计算函数,否则没法知道Q的值。所以需要换一种方式。
xxx状态空间不确定,也就是V(x)V(x)V(x)的值函数没法表示,可以考虑直接学习获得一个值函数V(x)V(x)V(x)
令Vθ(x)=θTxV_{\theta}(x)=\theta^TxVθ(x)=θTx,使用最小二乘法计算损失,为了使误差最小,使用梯度下降法,就是之前神经网络的那一坨的推导方式
可以得到参数向量θ\thetaθ的更新方式:
θ=θ+α(r+γθTx′−θTx)x\theta=\theta+\alpha(r+\gamma\theta^Tx^{\prime}-\theta^Tx)x θ=θ+α(r+γθTx′−θTx)x
x′x^{\prime}x′是下一时刻的状态。V(x)V(x)V(x)这个值函数出来了,因为Sarsa中是需要状态-动作函数Q(x,a)Q(x,a)Q(x,a),所以还需要做一下转换。两种装换形式
- 将上式中的xxx向量变成(x,a)(x,a)(x,a),增加一维,将动作放进去,直接计算得到的就是带动作的θ\thetaθ
- 新形成一个aaa向量进行计算。
最终的方式就是状态连续值版本的Sarsa算法:
模仿学习
如果状态集和动作集很广,而步数T要比较大时。这个搜索空间会比较巨大,很难短时间内完成策略的制定。如果此时有一部分专家数据,可以知道机器快速完成搜索和学习,那么就像机器去模仿这些专家数据,成为模仿学习。
假设有一批专家的决策轨迹数据:
τi=<s1i,a1i,s2i,a2i,…,sni+1i>\tau_i=<s_1^i,a_1^i,s_2^i,a_2^i,\dots,s_{n_i+1}^i> τi=<s1i,a1i,s2i,a2i,…,sni+1i>
其中,nin_ini为第iii条轨迹中的转移次数。
直接模仿学习
将上面的数据重新构造为:
D={(s1,a1),(s2,a2),…,(s∑i=1mni,a∑i=1mni),}D=\lbrace (s_1,a_1),(s_2,a_2),\dots,(s_{\sum_{i=1}^m{n_i}},a_{\sum_{i=1}^m{n_i}}),\rbrace D={(s1,a1),(s2,a2),…,(s∑i=1mni,a∑i=1mni),}
也就是将每个状态,动作的元素抽取出来。利用这样的一个数据集合去训练初始的策略模型,然后再在这个初始的策略模型基础上利用上述的强化学习模型进行学习,会缩短整个迭代次数。
逆强化学习
逆强化学习是试图从专家数据中获取一个奖赏函数,这个奖赏函数会使得策略让这些专家数据的出现概率最高。
其中的第5行代码就是通过各种转换获得的奖赏目标优化函数。
机器学习读书笔记:强化学习相关推荐
- 强化学习笔记-强化学习概述
强化学习笔记-强化学习概述 机器学习分类 强化学习与监督学习的异同点 强化学习基本原理 强化学习解决的是什么样的问题 强化学习分类 请分别解释随机性策略和确定性策略 回报.值函数.行为值函数三个指标的 ...
- Bishop 模式识别与机器学习读书笔记_ch1.1 机器学习概述
模式识别与机器学习-读书笔记 第一章 机器学习概述(I) 数据模式搜索问题是一个基础性的问题,有着悠久而成功的历史. 16世纪对第谷布拉赫的广泛天文观测使约翰内斯开普勒发现了行星运动的经验定律,从而为 ...
- AI人工智能开发的路径有三条,最成功的是机器学习技术:强化学习
https://www.toutiao.com/a6683382168732828174/ 2019-04-24 16:56:12 阿尔法围棋(AlphaGo为什么能够成为第一个击败人类职业围棋选手. ...
- 机器学习读书笔记(开篇)
新近到手一本<机器学习实战>(Peter Harringtom),兴奋之余,本着好记性不如烂笔头的真理,打算将读书的过程记录下来,形成读书笔记,重点记录自己所理解的算法思想与应用示例.本人 ...
- [Mitchell 机器学习读书笔记]——人工神经网络
1.简介 神经网络学习方法对于逼近实数值.离散值或向量值的目标函数提供了一种健壮性很强的方法.在现实中,学习解释复杂的现实世界中的传感器数据,人工神经网络(Artificial Neural Netw ...
- 李宏毅机器学习—读书笔记
李宏毅机器学习笔记(LeeML-Notes) leeml-notes 机器学习 人工智慧(Artificial Intelligence)是我们想要达成的目标,希望机器可以跟人一样的聪明.机器学习(M ...
- 北京内推 | 微软亚洲研究院机器学习组招聘强化学习方向研究型实习生
合适的工作难找?最新的招聘信息也不知道? AI 求职为大家精选人工智能领域最新鲜的招聘信息,助你先人一步投递,快人一步入职! 微软亚洲研究院 微软亚洲研究院机器学习组从理论.算法.应用等不同层面推动机 ...
- 读书笔记《学习之道》芭芭拉·奥克利 - 三 最后总结
使用作者的最后一章进行这篇读书笔记的结束语,因为书中描述的所有内容如果做不到也并卵,所以如果能做到作者最后总结的这些精炼的法则中的某些条进行学习,也应该有不错的学习效果了. 10个好的学习法则 1. ...
- 学习笔记|强化学习(Reinforcement Learning, RL)——让AlphaGo进化得比人类更强
文章目录 1. 题外话:人类棋手的最后赞礼 2. 强化学习概述 2.1 强化学习的目标也是要找一个Function 2.2 强化学习的三个基本步骤 2.2.1 定义一个function 2.2.2 定 ...
最新文章
- gradle转maven
- Oracle-批量修改语句及相关知识点
- 【博客美化】08.添加扩大/缩小浏览区域大小 按钮
- MySQL高级 - 案例 - 系统性能优化 - 读写分离概述
- ubuntu20.04安装OPTEE
- 程序员想早点下班被经理拒绝,一气之下要辞职,经理慌了
- 【Spring-AOP】自动代理类AnnotationAwareAspectJAutoProxyCreator
- Sketch 54.1 Shark 鲨鱼中文汉化特别版 Mac 设计师必备的原型UI设计工具
- Intouch System Platform IDE
- android.mk 系统签名,APK-安装系统认证签名的两种解决方法
- 【冬瓜哥雄文】高端存储系统江湖风云录!
- pe里怎么看不到计算机硬盘,进去pe系统找不到硬盘怎么回事_进入pe系统看不到硬盘如何解决-win7之家...
- 如何调试 fastlane 源码
- Word不计算封面、目录页数将正文页码修改为第几页共几页的格式
- 美国入境前的EVUS登记图文指南
- canvas粒子线条插件使用
- MATLAB中快捷注释方法和使用“%%”将代码分块运行方法
- sp/计算机产品与流通,计算机产品与流通杂志
- 【网络技术】(5)身份认证技术与访问控制------数字签名技术
- 一份完整的ACSII码表
热门文章
- Macbook Pro 201 装Win10 声卡_【Macbook安装Win10优化第一弹】用Dolby Atmos恢复应有的音质...
- 以太网之生成树与VLAN
- 在Linux中检索英语单词——字母q总是与u在一起吗?
- 吴恩达机器学习之逻辑回归(二分类)
- 为什么TCP握手是三次握手而不是两次
- 中e管家理财投资误碰的七个穴
- 解决Vue中Object.assign清空数据的报错
- Android程序测试
- (43)ObjectARX2015 + vs2012 JIG-双击实体的响应
- 什么是仿站?仿站有什么优势呢?