CS229 2017版作业4
课程视频地址:http://open.163.com/special/opencourse/machinelearning.html
课程主页:http://cs229.stanford.edu/
更具体的资料链接:https://www.jianshu.com/p/0a6ef31ff77a
作业地址:https://github.com/Doraemonzzz/CS229
参考资料:https://github.com/zyxue/stanford-cs229
这部分回顾2017版作业4。
1. Neural Networks: MNIST image classfication
(a)(b)(c)前向传播部分很简单,反向传播部分的推导请参考CS231作业1,其中如下代码
#计算第二层梯度
p3 = np.exp(scores) / p2.reshape(-1, 1)
p3[np.arange(N), y] -= 1
dW2 = X1.T.dot(p3) / N + 2 * reg * W2
db2 = np.sum(p3, axis=0) / N
grads["W2"] = dW2
grads["b2"] = db2
对应于这里的
N2, D2 = y.shape
t2 = y - labels
db2 = np.sum(t2, axis=0) / N2
dW2 = h.T.dot(t2) / N2
if Lambda != 0:
dW2 += 2 * Lambda * W2
dX2 = t2.dot(W2.T)
注意CS231的习题和这里最大的不同为前者的y是数值,即$0,1,…,9$的形式,而后者的则是one-hot的形式,所以以下两句代码作用相同:
#CS231
p3[np.arange(N), y] -= 1
#CS229
t2 = y - labels
在第一层中,只要知道sigmoid函数的导数为
即可,这部分的代码为:
#第一层梯度
N2, D2 = data.shape
t1 = h * (1 - h)
dW1 = data.T.dot(t1 * dX2) / N2
if Lambda != 0:
dW1 += 2 * Lambda * W1
db1 = np.sum(t1, axis=0) / N2
完整的代码见my_nn_starter.py文件。
2. EM Convergence
首先回顾定义以及不等式:
如果$\theta$最终收敛到$\theta’$,那么
所以
3. PCA
首先计算$f_u(x)$,设
带入原式可得
关于$\alpha $求导,并令导数为$0$可得
所以
所以我们的目标为求解如下问题
记
那么
所以
注意前一项是常数,所以原问题可以化为
因此可以构造拉格朗日乘子:
求梯度可得
令上式为$0$,那么
这说明$u$是$X^TX$的特征值,并且
所以$u$是$X^TX$最大特征值对应的特征向量,即第一主成分。
4. Independent components analysis
报错参考:安装sounddevice报错的解决方案。
这里更新公式为:
其中
注意我们有
所以恢复数据的公式为
代码如下:
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 29 13:49:57 2019
@author: qinzhen
"""
### Independent Components Analysis
###
### This program requires a working installation of:
###
### On Mac:
### 1. portaudio: On Mac: brew install portaudio
### 2. sounddevice: pip install sounddevice
###
### On windows:
### pip install pyaudio sounddevice
###
import sounddevice as sd
import numpy as np
Fs = 11025
def normalize(dat):
return 0.99 * dat / np.max(np.abs(dat))
def load_data():
mix = np.loadtxt('mix.dat')
return mix
def play(vec):
sd.play(vec, Fs, blocking=True)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def unmixer(X):
M, N = X.shape
W = np.eye(N)
anneal = [0.1, 0.1, 0.1, 0.05, 0.05, 0.05, 0.02, 0.02, 0.01, 0.01,
0.005, 0.005, 0.002, 0.002, 0.001, 0.001]
print('Separating tracks ...')
######## Your code here ##########
for alpha in anneal:
#打乱数据
np.random.permutation(X)
for i in range(M):
x = X[i, :].reshape(-1, 1)
WX = W.dot(x)
grad = (1 - 2 * sigmoid(WX)).dot(x.T) + np.linalg.inv(W.T)
W += alpha * grad
###################################
return W
def unmix(X, W):
S = np.zeros(X.shape)
######### Your code here ##########
S = X.dot(W.T)
##################################
return S
X = normalize(load_data())
for i in range(X.shape[1]):
print('Playing mixed track %d' % i)
play(X[:, i])
W = unmixer(X)
S = normalize(unmix(X, W))
for i in range(S.shape[1]):
print('Playing separated track %d' % i)
play(S[:, i])
5. Markov decision processes
(a)$\forall \pi$,定义
那么
所以
因此
注意由定义我们有
由对称性,不妨设
如果记
从而
因此
类似的,如果
那么记
依然可得
所以无论那种情形,我们都有
对左边关于$s$取最大值可得
(b)如果存在$V$使得
那么任取同样满足上述条件的$V_0$,即
那么
因此
所以
6.Reinforcement Learning: The inverted pendulum
首先是初始化:
#价值函数
value_function = np.random.uniform(0, 0.1, NUM_STATES)
#计数
tran_cnt = np.zeros((NUM_STATES, NUM_STATES, NUM_ACTIONS))
#概率
tran_prob = np.ones((NUM_STATES, NUM_STATES, NUM_ACTIONS)) / NUM_STATES
#记录奖励
reward_value = np.zeros(NUM_STATES)
#记录奖励总数
reward_cnt = np.zeros(NUM_STATES)
#奖励
state_reward = np.zeros(NUM_STATES)
第一步初始化价值函数为均匀分布,第二步记录用行动$a$从状态$b$到状态$c$的次数,第三步初始化状态转移概率$P_{sa}$,第四步记录累计奖励,第五步统计奖励次数,第六步是初始化奖励函数$R(s)$。
然后是对行动作出选择:
#期望收益,比较其大小
s0 = np.sum(tran_prob[state, :, 0] * value_function)
s1 = np.sum(tran_prob[state, :, 1] * value_function)
if s0 > s1:
action = 0
elif s0 < s1:
action = 1
else:
action = np.random.randint(0, 2)
上述代码第一步是计算
根据这一项选择采取哪种行动。
其次是每次行动后对统计量进行更新:
tran_cnt[state, new_state, action] += 1
reward_value[new_state] += R
reward_cnt[new_state] += 1
接着在到达最终状态后,更新价值函数,状态转移概率:
#统计在某个状态采取某个动作的次数
for i in range(NUM_ACTIONS):
for j in range(NUM_STATES):
#在状态j采取行动i的总数
num = np.sum(tran_cnt[j, :, i])
if num > 0:
tran_prob[j, :, i] = tran_cnt[j, :, i] / num
#更新奖励
state_reward[reward_cnt>0] = reward_value[reward_cnt>0] / reward_cnt[reward_cnt>0]
最后一步利用值迭代更新:
对每个状态$s$,初始化$V(s):=0$
重复直到收敛{
- 对每个状态,更新$V(s):=R(s) + \max_{a\in A}\gamma \sum_{s’\in S}
P_{sa}(s’) V(s’)$
}
- 对每个状态,更新$V(s):=R(s) + \max_{a\in A}\gamma \sum_{s’\in S}
代码如下
iterations = 0
while True:
#值迭代更新后的值
v0 = GAMMA * tran_prob[:, :, 0].dot(value_function) + state_reward
v1 = GAMMA * tran_prob[:, :, 1].dot(value_function) + state_reward
v = np.c_[v0, v1]
#取最大值
value_function_new = np.max(v, axis=1)
#计算更新幅度
delta = np.linalg.norm(value_function_new - value_function)
#更新价值函数
value_function = np.copy(value_function_new)
iterations += 1
#更新幅度变小,则停止循环
if delta < TOLERANCE:
break
#更新一次收敛的计数
if iterations == 1:
consecutive_no_learning_trials += 1
else:
consecutive_no_learning_trials = 0