13

संपादित करें (1/3/16): corresponding github issueमजबूती सीखने के कार्यक्रम में सक्रियण के बिना टेन्सफोर्लो ऑप्टिमाइज़र का उपयोग कैसे करें जो प्रत्येक पुनरावृत्ति के बाद नियंत्रण लौटाता है?

मैं समारोह सन्निकटन के साथ एक क्यू-लर्निंग एजेंट को लागू करने के Tensorflow (अजगर इंटरफेस) का उपयोग कर रहा स्टोकेस्टिक ढाल-वंश का उपयोग कर प्रशिक्षित किया। प्रयोग के प्रत्येक पुनरावृत्ति पर एजेंट में एक चरण कार्य को कहा जाता है कि नए इनाम और सक्रियण के आधार पर अनुमानक के पैरामीटर अपडेट करते हैं, और फिर प्रदर्शन करने के लिए एक नई क्रिया चुनते हैं।

  • एजेंट अपने राज्य-एक्शन मूल्य भविष्यवाणियों की गणना करता है एक कार्रवाई का चयन करने के:

    यहाँ समस्या (सुदृढीकरण सीखने शब्दजाल के साथ) है।

  • फिर नियंत्रण में एक और कार्यक्रम है जो पर्यावरण में एक कदम अनुकरण करता है।
  • अब एजेंट के चरण समारोह को अगले पुनरावृत्ति के लिए बुलाया जाता है। मैं अपने लिए ग्रेडियेंट की गणना करने के लिए टेन्सफोर्लो के ऑप्टिमाइज़र क्लास का उपयोग करना चाहता हूं। हालांकि, इसके लिए राज्य-क्रिया मूल्य भविष्यवाणियों की आवश्यकता होती है जिन्हें मैंने अंतिम चरण और उनके ग्राफ़ की गणना की थी। तो:
    • यदि मैं पूरे ग्राफ पर ऑप्टिमाइज़र चलाता हूं, तो उसे राज्य-क्रिया मान भविष्यवाणियों को दोबारा बदलना होगा।
    • लेकिन, यदि मैं एक चर के रूप में भविष्यवाणी (चुने हुए क्रिया के लिए) को संग्रहीत करता हूं, तो उसे ऑप्टीमाइज़र को प्लेसहोल्डर के रूप में खिलाएं, अब इसमें ग्रेडियेंट की गणना करने के लिए आवश्यक ग्राफ नहीं है।
    • मैं इसे सब एक ही sess.run() कथन में नहीं चला सकता, क्योंकि मुझे अगले अवलोकन और इनाम (लक्ष्य के लिए लक्ष्य में उपयोग करने के लिए) को नियंत्रण छोड़ना है और चयनित कार्रवाई को वापस करना है लॉस फंकशन)।

तो, वहाँ एक रास्ता है कि मैं कर सकते हैं (सुदृढीकरण सीखने शब्दजाल के बिना):

  1. कंप्यूट मेरी ग्राफ का हिस्सा, मान 1 लौटने।
  2. मूल्य 2
  3. की गणना करने के लिए कॉलिंग प्रोग्राम पर वापसी मूल्य 1 अगले पुनरावृत्ति में, मूल्य 1 की गणना करने वाले ग्राफ़ के भाग को पुन: संकलित किए बिना ग्रेडियेंट वंश के लिए मेरे हानि फ़ंक्शन के हिस्से के रूप में मान 2 का उपयोग करें।

    1. बस ढ़ाल हार्डकोड: यह वास्तव में सरल approximators मैं अब उपयोग कर रहा हूँ के लिए आसान होगा, लेकिन वास्तव में अगर असुविधाजनक होगा

    बेशक

    , मैं स्पष्ट समाधान पर विचार किया है मैं एक बड़े संकल्पक नेटवर्क में विभिन्न फिल्टर और सक्रियण कार्यों के साथ प्रयोग कर रहा था। यदि संभव हो तो मैं वास्तव में ऑप्टिमाइज़र क्लास का उपयोग करना चाहता हूं।

  4. एजेंट के भीतर से पर्यावरण सिमुलेशन को कॉल करें: This system ऐसा करता है, लेकिन यह मेरा अधिक जटिल बना देगा, और मॉड्यूलरिटी और संरचना को बहुत हटा देगा। तो, मैं यह नहीं करना चाहता।

मैंने कई बार एपीआई और व्हाइटपेपर के माध्यम से पढ़ा है, लेकिन एक समाधान के साथ आने लगते हैं। मैं ग्रेडियेंट की गणना करने के लिए ग्राफ़ में लक्ष्य को खिलाने के किसी तरीके से आने का प्रयास कर रहा था, लेकिन वह ग्राफ स्वचालित रूप से बनाने के लिए एक तरीके से नहीं आ सकता था।

यदि यह पता चला है कि यह अभी तक टेंसरफ्लो में संभव नहीं है, तो क्या आपको लगता है कि इसे एक नए ऑपरेटर के रूप में लागू करने के लिए बहुत जटिल होगा? (मैंने कुछ वर्षों में सी ++ का उपयोग नहीं किया है, इसलिए टेंसरफ्लो स्रोत थोड़ा डरावना दिखता है।) या क्या मैं टॉर्च जैसे कुछ स्विचिंग से बेहतर होगा, जिसमें प्रतीकात्मक भेदभाव के बजाय अनिवार्य भिन्नता ऑटोग्रैड है?

इस पर मेरी सहायता करने के लिए समय निकालने के लिए धन्यवाद। मैं इसे जितना संभव हो उतना संक्षिप्त बनाने की कोशिश कर रहा था।

संपादित करें: कुछ और खोज करने के बाद मैं this previously asked question पर आया। यह मेरी तुलना में थोड़ा अलग है (वे टॉर्च में प्रत्येक पुनरावृत्ति से दो बार एलएसटीएम नेटवर्क को अपडेट करने से बचने की कोशिश कर रहे हैं), और अभी तक कोई जवाब नहीं है।

''' 
-Q-Learning agent for a grid-world environment. 
-Receives input as raw rbg pixel representation of screen. 
-Uses an artificial neural network function approximator with one hidden layer 

2015 Jonathon Byrd 
''' 

import random 
import sys 
#import copy 
from rlglue.agent.Agent import Agent 
from rlglue.agent import AgentLoader as AgentLoader 
from rlglue.types import Action 
from rlglue.types import Observation 

import tensorflow as tf 
import numpy as np 

world_size = (3,3) 
total_spaces = world_size[0] * world_size[1] 

class simple_agent(Agent): 

    #Contants 
    discount_factor = tf.constant(0.5, name="discount_factor") 
    learning_rate = tf.constant(0.01, name="learning_rate") 
    exploration_rate = tf.Variable(0.2, name="exploration_rate") # used to be a constant :P 
    hidden_layer_size = 12 

    #Network Parameters - weights and biases 
    W = [tf.Variable(tf.truncated_normal([total_spaces * 3, hidden_layer_size], stddev=0.1), name="layer_1_weights"), 
    tf.Variable(tf.truncated_normal([hidden_layer_size,4], stddev=0.1), name="layer_2_weights")] 
    b = [tf.Variable(tf.zeros([hidden_layer_size]), name="layer_1_biases"), tf.Variable(tf.zeros([4]), name="layer_2_biases")] 

    #Input placeholders - observation and reward 
    screen = tf.placeholder(tf.float32, shape=[1, total_spaces * 3], name="observation") #input pixel rgb values 
    reward = tf.placeholder(tf.float32, shape=[], name="reward") 

    #last step data 
    last_obs = np.array([1, 2, 3], ndmin=4) 
    last_act = -1 

    #Last step placeholders 
    last_screen = tf.placeholder(tf.float32, shape=[1, total_spaces * 3], name="previous_observation") 
    last_move = tf.placeholder(tf.int32, shape = [], name="previous_action") 

    next_prediction = tf.placeholder(tf.float32, shape = [], name="next_prediction") 

    step_count = 0 

    def __init__(self): 
     #Initialize computational graphs 
     self.q_preds = self.Q(self.screen) 
     self.last_q_preds = self.Q(self.last_screen) 
     self.action = self.choose_action(self.q_preds) 
     self.next_pred = self.max_q(self.q_preds) 
     self.last_pred = self.act_to_pred(self.last_move, self.last_q_preds) # inefficient recomputation 
     self.loss = self.error(self.last_pred, self.reward, self.next_prediction) 
     self.train = self.learn(self.loss) 
     #Summaries and Statistics 
     tf.scalar_summary(['loss'], self.loss) 
     tf.scalar_summary('reward', self.reward) 
     #w_hist = tf.histogram_summary("weights", self.W[0]) 
     self.summary_op = tf.merge_all_summaries() 
     self.sess = tf.Session() 
     self.summary_writer = tf.train.SummaryWriter('tensorlogs', graph_def=self.sess.graph_def) 


    def agent_init(self,taskSpec): 
     print("agent_init called") 
     self.sess.run(tf.initialize_all_variables()) 

    def agent_start(self,observation): 
     #print("agent_start called, observation = {0}".format(observation.intArray)) 
     o = np.divide(np.reshape(np.asarray(observation.intArray), (1,total_spaces * 3)), 255) 
     return self.control(o) 

    def agent_step(self,reward, observation): 
     #print("agent_step called, observation = {0}".format(observation.intArray)) 
     print("step, reward: {0}".format(reward)) 
     o = np.divide(np.reshape(np.asarray(observation.intArray), (1,total_spaces * 3)), 255) 

     next_prediction = self.sess.run([self.next_pred], feed_dict={self.screen:o})[0] 

     if self.step_count % 10 == 0: 
      summary_str = self.sess.run([self.summary_op, self.train], 
       feed_dict={self.reward:reward, self.last_screen:self.last_obs, 
       self.last_move:self.last_act, self.next_prediction:next_prediction})[0] 

      self.summary_writer.add_summary(summary_str, global_step=self.step_count) 
     else: 
      self.sess.run([self.train], 
       feed_dict={self.screen:o, self.reward:reward, self.last_screen:self.last_obs, 
       self.last_move:self.last_act, self.next_prediction:next_prediction}) 

     return self.control(o) 

    def control(self, observation): 
     results = self.sess.run([self.action], feed_dict={self.screen:observation}) 
     action = results[0] 

     self.last_act = action 
     self.last_obs = observation 

     if (action==0): # convert action integer to direction character 
      action = 'u' 
     elif (action==1): 
      action = 'l' 
     elif (action==2): 
      action = 'r' 
     elif (action==3): 
      action = 'd' 
     returnAction=Action() 
     returnAction.charArray=[action] 
     #print("return action returned {0}".format(action)) 
     self.step_count += 1 
     return returnAction 

    def Q(self, obs): #calculates state-action value prediction with feed-forward neural net 
     with tf.name_scope('network_inference') as scope: 
      h1 = tf.nn.relu(tf.matmul(obs, self.W[0]) + self.b[0]) 
      q_preds = tf.matmul(h1, self.W[1]) + self.b[1] #linear activation 
      return tf.reshape(q_preds, shape=[4]) 

    def choose_action(self, q_preds): #chooses action epsilon-greedily 
     with tf.name_scope('action_choice') as scope: 
      exploration_roll = tf.random_uniform([]) 
      #greedy_action = tf.argmax(q_preds, 0) # gets the action with the highest predicted Q-value 
      #random_action = tf.cast(tf.floor(tf.random_uniform([], maxval=4.0)), tf.int64) 

      #exploration rate updates 
      #if self.step_count % 10000 == 0: 
       #self.exploration_rate.assign(tf.div(self.exploration_rate, 2)) 

      return tf.select(tf.greater_equal(exploration_roll, self.exploration_rate), 
       tf.argmax(q_preds, 0), #greedy_action 
       tf.cast(tf.floor(tf.random_uniform([], maxval=4.0)), tf.int64)) #random_action 

     ''' 
     Why does this return NoneType?: 

     flag = tf.select(tf.greater_equal(exploration_roll, self.exploration_rate), 'g', 'r') 
     if flag == 'g': #greedy 
      return tf.argmax(q_preds, 0) # gets the action with the highest predicted Q-value 
     elif flag == 'r': #random 
      return tf.cast(tf.floor(tf.random_uniform([], maxval=4.0)), tf.int64) 
     ''' 

    def error(self, last_pred, r, next_pred): 
     with tf.name_scope('loss_function') as scope: 
      y = tf.add(r, tf.mul(self.discount_factor, next_pred)) #target 
      return tf.square(tf.sub(y, last_pred)) #squared difference error 


    def learn(self, loss): #Update parameters using stochastic gradient descent 
     #TODO: Either figure out how to avoid computing the q-prediction twice or just hardcode the gradients. 
     with tf.name_scope('train') as scope: 
      return tf.train.GradientDescentOptimizer(self.learning_rate).minimize(loss, var_list=[self.W[0], self.W[1], self.b[0], self.b[1]]) 


    def max_q(self, q_preds): 
     with tf.name_scope('greedy_estimate') as scope: 
      return tf.reduce_max(q_preds) #best predicted action from current state 

    def act_to_pred(self, a, preds): #get the value prediction for action a 
     with tf.name_scope('get_prediction') as scope: 
      return tf.slice(preds, tf.reshape(a, shape=[1]), [1]) 


    def agent_end(self,reward): 
     pass 

    def agent_cleanup(self): 
     self.sess.close() 
     pass 

    def agent_message(self,inMessage): 
     if inMessage=="what is your name?": 
      return "my name is simple_agent"; 
     else: 
      return "I don't know how to respond to your message"; 

if __name__=="__main__": 
    AgentLoader.loadAgent(simple_agent()) 

उत्तर

14

अभी क्या आप क्या करना चाहते Tensorflow (0.6) में बहुत मुश्किल है:

यहाँ कुछ कोड है कि अगर मदद करता है। आपकी सबसे अच्छी शर्त बुलेट को काटने और सक्रियण को दोबारा जोड़ने की लागत पर कई बार कॉल करना है। हालांकि, हम आंतरिक रूप से इस मुद्दे से बहुत अवगत हैं। एक प्रोटोटाइप "आंशिक रन" समाधान कामों में है, लेकिन अभी इसके पूरा होने के लिए कोई समयरेखा नहीं है। चूंकि वास्तव में संतोषजनक उत्तर के लिए टेन्सफोर्लो को संशोधित करने की आवश्यकता हो सकती है, इसलिए आप इसके लिए एक गिथब मुद्दा भी बना सकते हैं और देख सकते हैं कि किसी और के पास इस पर कुछ कहना है या नहीं।

संपादित करें: partial_run लिए प्रायोगिक समर्थन में है https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/client/session.py#L317

+0

एक [GitHub मुद्दे] मेड (https://github.com/tensorflow/tensorflow/issues/672)। –

संबंधित मुद्दे