1、交叉熵理解
https://www.cnblogs.com/kyrieng/p/8694705.html (信息量爲什麼取log)
2、前向傳播 反向傳播 複習
英文版:http://neuralnetworksanddeeplearning.com/chap2.html
中文版 https://blog.csdn.net/qq_16137569/article/details/81449209(全連接)
https://blog.csdn.net/qq_16137569/article/details/81477906 (卷積)
https://www.cnblogs.com/pinard/p/6494810.html (卷積)
2.2 RNN複習
https://zhuanlan.zhihu.com/p/28054589(RNN變種圖解)
https://www.cnblogs.com/pinard/p/6519110.html https://blog.csdn.net/zhaojc1995/article/details/80572098(lstm詳解)
tensorflow實現RNN char:https://zhuanlan.zhihu.com/p/28196873
tensorflow實現lstm minist手寫數字分類:https://blog.csdn.net/u010858605/article/details/78696325
3、強化學習複習
《python強化學習實戰 印度蘇達桑》代碼地址:https://github.com/PacktPublishing/Deep-Reinforcement-Learning-Hands-On
英文版原書地址(含代碼):https://github.com/sudharsan13296/Hands-On-Reinforcement-Learning-With-Python
一、策略迭代
初始化策略並計算該策略下的狀態值函數(策略評估),根據每個狀態值函數改進策略(策略改善),重複策略評估和策略改善步驟,直到策略收斂。
# 策略評估
def policy_evaluation(self, agent, max_iter=-1):
"""
:param obj agent: 智能體
:param int max_iter: 最大迭代數
"""
iteration = 0
while True:
iteration += 1
new_value_pi = agent.value_pi.copy()
# 對每個state計算v(s)
for i in range(1, agent.s_len):
ac = agent.pi[i]
transition = agent.p[ac, i, :]
value_sa = np.dot(transition, agent.r + agent.gamma * agent.value_pi)
new_value_pi[i] = value_sa
# 前後2次值函數的變化小於一個閾值,結束
diff = np.sqrt(np.sum(np.power(agent.value_pi - new_value_pi, 2)))
if diff < 1e-6:
break
else:
agent.value_pi = new_value_pi
if iteration == max_iter:
break
# 策略提升
def policy_improvement(self, agent):
"""
:param obj agent: 智能體
"""
# 初始化新策略
new_policy = np.zeros_like(agent.pi)
for i in range(1, agent.s_len):
for j in range(0, agent.a_len):
# 計算每一個狀態行動值函數
agent.value_q[i, j] = np.dot(agent.p[j, i, :], agent.r + agent.gamma * agent.value_pi)
# 選出每個狀態下的最優行動
max_act = np.argmax(agent.value_q[i, :])
new_policy[i] = max_act
if np.all(np.equal(new_policy, agent.pi)):
return False
else:
agent.pi = new_policy
return True
# 策略迭代
def policy_iteration(self, agent):
"""
:param obj agent: 智能體
"""
iteration = 0
while True:
iteration += 1
self.policy_evaluation(agent)
ret = self.policy_improvement(agent)
if not ret:
break
print('Iter {} rounds converge'.format(iteration))
二、值迭代
對每一個當前狀態 s ,對每個可能的動作 a 都計算一下采取這個動作後到達的下一個狀態的期望價值。看看哪個動作可以到達的狀態的期望價值函數最大,就將這個最大的期望價值函數作爲當前狀態的價值函數。循環執行這個步驟,直到價值函數收斂。(值迭代是根據狀態期望值選擇動作,而策略迭代是先估計狀態值然後修改策略)
class ValueIteration(object):
def value_iteration(self, agent, max_iter=-1):
"""
:param obj agent: 智能體
:param int max_iter: 最大迭代數
"""
iteration = 0
while True:
iteration += 1
# 保存算出的值函數
new_value_pi = np.zeros_like(agent.value_pi)
for i in range(1, agent.s_len):
value_sas = []
for j in range(0, agent.a_len):
# 對每一個狀態s和行動a,計算值函數
value_sa = np.dot(agent.p[j, i, :], agent.r + agent.gamma * agent.value_pi)
value_sas.append(value_sa)
# 從每個行動中,選出最好的值函數
new_value_pi[i] = max(value_sas)
# 前後2次值函數的變化小於一個閾值,結束
diff = np.sqrt(np.sum(np.power(agent.value_pi - new_value_pi, 2)))
if diff < 1e-6:
break
else:
agent.value_pi = new_value_pi
if iteration == max_iter:
break
print('Iter {} rounds converge'.format(iteration))
for i in range(1, agent.s_len):
for j in range(0, agent.a_len):
# 計算收斂後值函數的狀態-行動值函數
agent.value_q[i, j] = np.dot(agent.p[j, i, :], agent.r + agent.gamma * agent.value_pi)
# 取出最大的行動
max_act = np.argmax(agent.value_q[i, :])
agent.pi[i] = max_act
值迭代與策略迭代相同、不同之處:
1、兩個方法最終都求出策略函數和值函
2、策略迭代是等值函數穩定以後再改進策略,值迭代每一次都在改進策略並且更新值函數,一直到值函數收斂。
三、基於蒙特卡洛和基於TD_error
前者經過多次由起始到終止的實驗,利用經驗平均值估計狀態值函數;後者根據本次和下一次(或者下好多次)的差值更新狀態值函數
蒙特卡洛:
TD_error: ,arfa爲步長
時序差分法和蒙特卡洛方法的區別主要有:
1)蒙特卡洛方法要等到最後結果才能學習,而時序差分法可以在任一階段進行學習,具有更快速更靈活的更新狀態進行估值。
2)時序差分法是基於即時獎勵和下一狀態的預估價值來替代當前狀態在狀態序列結束時可能得到的回報,是當前狀態價值的有偏估計。而蒙特卡洛法則使用實際的收穫來更新狀態價值,是某一狀態價值的無偏估計(注:其實這裏的本質上是是否求期望的問題,蒙特卡洛通過採樣多條序列來求期望,可以代替總體樣本的無偏估計,但是因爲序列的多樣性導致方差較大,而時序差分法是直接預估下一狀態的值來更新當前狀態的值函數,這種預估本身就和真實值存在一定的偏差,但也因爲只用到了下一狀態的值,因此隨機性較小,方差相對來說更小)。
3)時序差分法的方差較蒙特卡洛方法更小,且對初始值敏感,但比蒙特卡洛方法更高效。時序差分法不止是有單步序列,還可以擴展到N步,當N足夠大,甚至趨於無窮時,就等價於蒙特卡洛方法了。時序差分法可以分爲在線策略(on-policy,也可稱爲同策略)和 離線策略(off-policy,也可稱爲異策略)。目前在線策略最常見的算法是SARSA算法,離線策略最常見的是Q-Learning算法。
四、DQN
DQN對Q-Learning的修改主要有三個方面:1)DQN利用深度卷積神經網絡逼近值函數。2)DQN利用了經驗回放 訓練強化學習的學習過程。3)DQN設置了目標網絡單獨處理TD_error,該網絡的參數每隔幾步纔會更新。
Q網絡參數更新:均方誤差損失函數,梯度反向傳播
參考:知乎大佬https://zhuanlan.zhihu.com/p/26052182
在第[12]行,利用了經驗回放;在[13]行利用了獨立的目標網絡;第[15]行,更新動作值函數逼近網絡參數;第[17]行更新目標網絡參數. 翻譯如下:
參考:https://www.cnblogs.com/jiangxinyang/p/10112381.html
代碼來自https://github.com/ljpzzz/machinelearning/tree/master/reinforcement-learning
其中,對於經驗回放在代碼中的具體用法:在算法剛開始跑的時候,經驗回放池的數據從無到有,這時是不會去訓練Q網絡的,只有當經驗回放池的數據量大於BATCH_SIZE,纔開始訓練。此後由於經驗回放池的數據會一直增多,回放池的大小是REPLAY_SIZE,如果池子滿了,而且一條新的交互數據到了,我們就從回放池裏面刪除一條最老的數據。然後只要經驗回放池裏的數據量大於我們用於需要採樣的樣本量BATCH_SIZE,就去訓練Q網絡。這段時間開始,每多一條新的環境交互數據,就會訓練Q網絡一次。
五、Double DQN
選擇動作和動作評估(用來更新值函數)選用兩個Q網絡,以防止估計值函數大於實際值。
#DoubleDQN
# Step 2: calculate y
y_batch = []
current_Q_batch = self.Q_value.eval(feed_dict={self.state_input: next_state_batch})
max_action_next = np.argmax(current_Q_batch, axis=1)
target_Q_batch = self.target_Q_value.eval(feed_dict={self.state_input: next_state_batch})
for i in range(0,BATCH_SIZE):
done = minibatch[i][4]
if done:
y_batch.append(reward_batch[i])
else :
target_Q_value = target_Q_batch[i, max_action_next[i]]
##這是與DQN不同的地方,在Q網絡中選擇使Q(S')最大的action,
然後在目標Q'網絡中找到該action對應的Q'(S')值來更新y
y_batch.append(reward_batch[i] + GAMMA * target_Q_value)
##DQN
# Step 2: calculate y
y_batch = []
Q_value_batch = self.target_Q_value.eval(feed_dict={self.state_input:next_state_batch})
for i in range(0,BATCH_SIZE):
done = minibatch[i][4]
if done:
y_batch.append(reward_batch[i])
else :
y_batch.append(reward_batch[i] + GAMMA * np.max(Q_value_batch[i]))
注意:(1)Double DQN是先在Q網絡中找最大的Q(S')對應的action_max ,然後在目標Q’網絡中找到action_max對應的Q'(S')值去更新y。(2)Q'目標網絡的參數是從Q網絡中定期(代碼中是episode%10==0時)複製更新。但是經驗池中有足夠的經驗以後,Q網絡會不停地更新,Q’保持不變。然後每10episode再從Q網絡複製更新一次Q'。
我的疑問: Q‘目標網絡的參數是從Q網絡中定期(代碼中是episode%10==0時)複製更新的,那它們此時計算出來的Q值是一樣的對嗎?只不過在其他9次episode中,Q網絡不停地更新,而Q'保持不變。
那這樣的話,大體上Q'和Q參數變化趨勢還是一樣的,爲什麼就解決了過估計呢?
另外,爲什麼Q'網絡參數要從Q網絡中複製而來?爲什麼不是自己更新呢?
劉建平老師:這個要考慮Q’網絡的作用,是解耦,儘可能的保證一定的獨立性,同時參數總體趨勢還是和Q一致。期望通過延時更新達到獨立的目的。如果Q‘也和Q一樣進行訓練的話,那麼複製參數沒有意義,會把Q‘的訓練搞亂,達不到獨立的目的。
多個Q網絡各個訓練在其他場景也是可以做的,比如A3C裏面,就是多個網絡獨立訓練。它的目的是加快訓練,達到並行的目的,而不是獨立的目的。
六、優先回放(Prioritized Replay)DQN
一個理想的標準是智能體學習的效率越高,權重越大。符合該標準的一個選擇是TD偏差δδ。TD偏差越大,說明該狀態處的值函數與TD目標的差距越大,智能體的更新量越大,因此該處的學習效率越高。
七、Dueling DQN
動作值函數分解爲 狀態值函數(僅與狀態有關)+優勢函數(與狀態動作都有關係)。因此,一共有兩個相同結構的Q網絡,每個Q網絡都有狀態函數和優勢函數的定義,以及組合後的Q網絡輸出。
def create_Q_network(self):
# input layer
self.state_input = tf.placeholder("float", [None, self.state_dim])
# network weights
with tf.variable_scope('current_net'):
W1 = self.weight_variable([self.state_dim,20])
b1 = self.bias_variable([20])
# hidden layer 1
h_layer_1 = tf.nn.relu(tf.matmul(self.state_input,W1) + b1)
# hidden layer for state value
with tf.variable_scope('Value'):
W21= self.weight_variable([20,1])
b21 = self.bias_variable([1])
self.V = tf.matmul(h_layer_1, W21) + b21
# hidden layer for action value
with tf.variable_scope('Advantage'):
W22 = self.weight_variable([20,self.action_dim])
b22 = self.bias_variable([self.action_dim])
self.A = tf.matmul(h_layer_1, W22) + b22
# Q Value layer
self.Q_value = self.V + (self.A - tf.reduce_mean(self.A, axis=1, keep_dims=True))
with tf.variable_scope('target_net'):
W1t = self.weight_variable([self.state_dim,20])
b1t = self.bias_variable([20])
# hidden layer 1
h_layer_1t = tf.nn.relu(tf.matmul(self.state_input,W1t) + b1t)
# hidden layer for state value
with tf.variable_scope('Value'):
W2v = self.weight_variable([20,1])
b2v = self.bias_variable([1])
self.VT = tf.matmul(h_layer_1t, W2v) + b2v
# hidden layer for action value
with tf.variable_scope('Advantage'):
W2a = self.weight_variable([20,self.action_dim])
b2a = self.bias_variable([self.action_dim])
self.AT = tf.matmul(h_layer_1t, W2a) + b2a
# Q Value layer
self.target_Q_value = self.VT + (self.AT - tf.reduce_mean(self.AT, axis=1, keep_dims=True))
其餘代碼,和DQN的一樣。https://github.com/ljpzzz/machinelearning/tree/master/reinforcement-learning
八、策略梯度法
在基於值函數方法中,我們用參數近似表示V值或者Q值,迭代使其變大;在基於策略的方法中,我們用參數近似表示策略,用蒙特卡洛方法近似得到V(迭代使得在策略下的累計回報變大)。
def create_softmax_network(self):
#最常用的策略函數就是softmax,它主要應用於離散空間中,
softmax策略使用描述狀態和行爲的特徵與參數θ的線性組合來權衡一個行爲發生的機率
# network weights
W1 = self.weight_variable([self.state_dim, 20])
b1 = self.bias_variable([20])
W2 = self.weight_variable([20, self.action_dim])
b2 = self.bias_variable([self.action_dim])
# input layer
self.state_input = tf.placeholder("float", [None, self.state_dim])
self.tf_acts = tf.placeholder(tf.int32, [None, ], name="actions_num")
self.tf_vt = tf.placeholder(tf.float32, [None, ], name="actions_value")
# hidden layers
h_layer = tf.nn.relu(tf.matmul(self.state_input, W1) + b1)
# softmax layer
self.softmax_input = tf.matmul(h_layer, W2) + b2
#softmax output
self.all_act_prob = tf.nn.softmax(self.softmax_input, name='act_prob')
self.neg_log_prob = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=self.softmax_input,
labels=self.tf_acts)
self.loss = tf.reduce_mean(self.neg_log_prob * self.tf_vt)
# softmax交叉熵損失函數和狀態價值函數的乘積,用交softmax是爲了求真實值和實際結果的分佈
#平均交叉熵應該是先計算batch中每一個樣本的交叉熵後取平均計算得到的,而利用tf.reduce_mean函數其實計算的是整個矩陣的平均值
self.train_op = tf.train.AdamOptimizer(LEARNING_RATE).minimize(self.loss)
def choose_action(self, observation):#用softmax網絡計算的概率選擇action
prob_weights = self.session.run(self.all_act_prob, feed_dict={self.state_input: observation[np.newaxis, :]})
action = np.random.choice(range(prob_weights.shape[1]), p=prob_weights.ravel()) # select action w.r.t the actions prob
return action
def learn(self):
discounted_ep_rs = np.zeros_like(self.ep_rs)
running_add = 0
for t in reversed(range(0, len(self.ep_rs))):
running_add = running_add * GAMMA + self.ep_rs[t]
discounted_ep_rs[t] = running_add
discounted_ep_rs -= np.mean(discounted_ep_rs)
discounted_ep_rs /= np.std(discounted_ep_rs)
#rs 表示一組狀態序列中的歸一化回報吧?不是Q值
# train on episode
self.session.run(self.train_op, feed_dict={
#這裏的feed_dict是每個step存下來的一條從起點到終點的軌跡 的狀態,action,累計回報
self.state_input: np.vstack(self.ep_obs),
self.tf_acts: np.array(self.ep_as),
self.tf_vt: discounted_ep_rs,
})
self.ep_obs, self.ep_as, self.ep_rs = [], [], [] # empty episode data
參考:https://www.cnblogs.com/pinard/p/10137696.html
九、Actor-Critic
在策略梯度方法中,策略函數就是Actor,用來更新策略、執行動作選擇,而V值(或Q值)是用蒙特卡洛的方法,累計回報取平均得到的。在AC中,增加一個評估函數,用新的網絡參數近似V值(Q值),就像DQN一樣,評價策略更新得好不好。
我對此的疑問:在AC裏面,策略更新有專門的更新公式,但是評估更新用的是loss。爲什麼不能反過來?或者是,兩個都用loss?兩個網絡的更新方式不同,原因是什麼? 師兄解答:其實都是用梯度下降法優化參數,只是對應的目的不同。
actor策略梯度更新公式:
critic 更新:均方差損失函數
####首先,choose_action()的結果來自Actor網絡:用actor網絡最後一層輸出值經過softmax選擇action,env.step後得到r和nextState。
h_layer = tf.nn.relu(tf.matmul(self.state_input, W1) + b1)
# softmax layer
self.softmax_input = tf.matmul(h_layer, W2) + b2
# softmax output
self.all_act_prob = tf.nn.softmax(self.softmax_input, name='act_prob')
def choose_action(self, observation):
prob_weights = self.session.run(self.all_act_prob, feed_dict={self.state_input: observation[np.newaxis, :]})
action = np.random.choice(range(prob_weights.shape[1]), p=prob_weights.ravel()) # select action w.r.t the actions prob
return action
####Q_value由critic網絡得到。把由Actor求到的action、r、nextState輸入critic,得到td_error。
####critic網絡根據td_error 更新參數,目的是減小TDerror
def create_training_method(self):
self.next_value = tf.placeholder(tf.float32, [1,1], "v_next")
self.reward = tf.placeholder(tf.float32, None, 'reward')
with tf.variable_scope('squared_TD_error'):
self.td_error = self.reward + GAMMA * self.next_value - self.Q_value
self.loss = tf.square(self.td_error)
with tf.variable_scope('train'):
self.train_op = tf.train.AdamOptimizer(self.epsilon).minimize(self.loss)
def train_Q_network(self, state, reward, next_state):
s, s_ = state[np.newaxis, :], next_state[np.newaxis, :]
v_ = self.session.run(self.Q_value, {self.state_input: s_})
td_error, _ = self.session.run([self.td_error, self.train_op],
{self.state_input: s, self.next_value: v_, self.reward: reward})
return td_error
####Actor網絡根據td_error和策略更新參數,目的是大化當前策略的價值
self.neg_log_prob = tf.nn.softmax_cross_entropy_with_logits(logits=self.softmax_input,
labels=self.tf_acts)
self.exp = tf.reduce_mean(self.neg_log_prob * self.td_error)
#這裏需要最大化當前策略的價值,因此需要最大化self.exp,即最小化-self.exp
self.train_op = tf.train.AdamOptimizer(LEARNING_RATE).minimize(-self.exp)
疑問: AC 算法存在難以收斂的問題。(爲什麼呢?)
critic_policy本身的問題:1) 比較難應用到隨機型策略(stochastic policy)和連續的動作空間。2) value function的微小變化會引起策略變化巨大,從而影響訓練收斂性。尤其是引入函數近似(function approximation,FA)後,雖然算法泛化能力提高了,但也引入了bias,從而使得訓練的收斂性更加難以保證。
actor_policy的問題:通過將策略參數化,從而直接學習策略。這樣做的好處是與前者相比擁有更好的收斂性,以及適用於高維連續動作空間及stochastic policy。但缺點包括梯度估計的變化幅度比較高,且容易收斂到非最優解。另外因爲每次梯度的估計不依賴以往的估計,意味着無法充分利用老的信息,因此數據利用率低。
actor_critic :一方面actor學習策略,而策略更新依賴critic估計的value function;另一方面critic估計value function,而value function又是策略的函數。Policy和value function互爲依賴,相互影響,因此更不容易收斂了。
改進方法:在DQN中,爲了方便收斂使用了經驗回放的技巧。A3C利用多線程的方法,同時在多個線程裏面分別和環境進行交互學習,每個線程都把學習的成果彙總起來,整理保存在一個公共的地方。並且,定期從公共的地方把大家的齊心學習的成果拿回來,指導自己和環境後面的學習交互。通過這種方法,A3C避免了經驗回放相關性過強的問題,同時做到了異步併發的學習模型。
A3C的優化主要有3點,分別是異步訓練框架,網絡結構優化,Critic評估點的優化
參考:https://www.cnblogs.com/pinard/p/10334127.html
十、A3C:Asynchronous Advantage Actor-critic 異步優勢策略評估
由於AC算法難以收斂的問題,A3C採用DQN中經驗回放的技巧,並且爲了避免回放池經驗數據相關性太強,用於訓練的時候效果很可能不佳的問題,A3C採用多線程的方法,同時在多個線程裏面分別和環境進行交互學習,每個線程都把學習的成果彙總起來,整理保存在一個公共的地方。並且,定期從公共的地方把大家的齊心學習的成果拿回來,指導自己和環境後面的學習交互。
因此,A3C比AC做出的優化是:
1、異步訓練
Global Network是所有線程共享的公共部分,包括Actor和Critic兩個功能。下面有n個worker線程,每個線程裏有和公共的神經網絡一樣的網絡結構,每個線程會獨立的和環境進行交互得到經驗數據,計算自己線程裏的損失函數和梯度,去更新公共網絡的參數(此時並不更新自己的網絡參數),每隔一段時間,從公共網絡複製參數爲自己的參數。
2、網絡結構優化
AC中分別有actor 和critic兩個網絡,而A3C把它們合併了,也就是用一個網絡可以同時輸出policy和value。
3、critic優化
AC中的優勢函數只用到了本次reward、本次V值和下一狀態的V值。公式:
在A3C中,使用了n步採樣,以加速收斂。採樣值由經驗池提供。這樣A3C中使用的優勢函數表達爲:
十一、DDPG:Deep Deterministic Policy Gradient 深度確定性策略梯度
Deep: 採用神經網絡擬合策略和評價函數
Deterministic: actor 策略輸出只有一個結果,每次只確定一個action。(而不像普通AC,得到的是很多個action的概率)
Policy Gradient: 採用策略梯度下降,分別有actor和critic 當前網絡和目標網絡共四個網絡,目標網絡參數定期從當前網絡複製更新。
1. Actor當前網絡:負責策略網絡參數θ 的迭代更新,負責根據當前狀態S選擇當前動作A,用於和環境交互生成S′,R 。
2. Actor目標網絡:負責根據經驗回放池中採樣的下一狀態S′選擇最優下一動作A' 。網絡參數θ′定期從θ複製。
3. Critic當前網絡:負責價值網絡參數w的迭代更新,負責計算當前Q值Q(S,A,w) 。目標Q值yi=R+γQ′(S′,A′,w′)
4. Critic目標網絡:負責計算目標Q值中的Q′(S′,A′,w′) 部分。網絡參數w′定期從w複製。
actor策略梯度計算:
##### main 中
a = ddpg.choose_action(s) #經過actor當前網絡,得到在action連續範圍內的一個數
a = np.clip(np.random.normal(a, var), -2, 2)
#numpy.clip(a, a_min, a_max, out=None)把數組值限制在一個範圍內
#numpy.random.normal(loc=0.0, scale=1.0, size=None),從均值爲loc,方差爲scale的正態分佈,輸出的shape,默認爲None,只輸出一個值
# add randomness to action selection for exploration 用正態分佈的形式增加探索action
s_, r, done, info = env.step(a)
ddpg.store_transition(s, a, r / 10, s_)
if ddpg.pointer > MEMORY_CAPACITY:
var *= .9995 # decay the action randomness
ddpg.learn()
s = s_
ep_reward += r
###四個網絡
with tf.variable_scope('Actor'):
self.a = self._build_a(self.S, scope='eval', trainable=True)#由actor當前網絡得到a
a_ = self._build_a(self.S_, scope='target', trainable=False)#由actor目標網絡得到s'的a'
with tf.variable_scope('Critic'):
# assign self.a = a in memory when calculating q for td_error,
# otherwise the self.a is from Actor when updating Actor
q = self._build_c(self.S, self.a, scope='eval', trainable=True)#由critic當前網絡得到q
q_ = self._build_c(self.S_, a_, scope='target', trainable=False)#critic目標網絡得到q_
###網絡更新
q_target = self.R + GAMMA * q_
# in the feed_dic for the td_error, the self.a should change to actions in memory
td_error = tf.losses.mean_squared_error(labels=q_target, predictions=q)#用q q_計算tderror,更新critic網絡
self.ctrain = tf.train.AdamOptimizer(LR_C).minimize(td_error, var_list=self.ce_params)
a_loss = - tf.reduce_mean(q) # maximize the q
self.atrain = tf.train.AdamOptimizer(LR_A).minimize(a_loss, var_list=self.ae_params)#更新actor網絡以增大q