{"id":370658,"date":"2024-05-21T04:30:24","date_gmt":"2024-05-21T04:30:24","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=370658"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=370658","title":{"rendered":"<span>\u041e\u0441\u043d\u043e\u0432\u044b Actor-Critic \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/308\/eb3\/ec1\/308eb3ec1392ee8d73af35d579a6492e.png\" width=\"780\" height=\"439\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/308\/eb3\/ec1\/308eb3ec1392ee8d73af35d579a6492e.png\"\/><\/figure>\n<p><em>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<\/em><\/p>\n<p><strong>Actor-Critic<\/strong> \u2014 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0432 RL, \u0441\u0443\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 \u043d\u0430 \u0441\u043b\u043e\u0432\u0430\u0445, \u043e\u043d \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043a\u0430\u043a <em>policy-based<\/em> \u0438 \u043e\u0446\u0435\u043d\u043a\u0438 <em>value-based<\/em>. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043b\u0438\u0446\u0430: <em>Actor<\/em> \u0438 <em>Critic<\/em><strong>. Actor \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0431\u043e\u0440 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439,<\/strong> \u0442.\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b. <strong>Critic \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0438\u043b\u0438 \u043f\u043b\u043e\u0445\u043e Actor \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439<\/strong>, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c \u0447\u0435\u0440\u0435\u0437 \u043e\u0446\u0435\u043d\u043a\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 Actor&#8217;a. <\/p>\n<h4>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 Actor<\/h4>\n<p>Actor \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0431\u043e\u0440 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0433\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b. Actor \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u0430\u043a \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043f\u043f\u0440\u043e\u043a\u0441\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e Actor, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e TensorFlow:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras import layers  class SimpleActorModel(tf.keras.Model):     def __init__(self, action_size):         super(SimpleActorModel, self).__init__()         self.dense1 = layers.Dense(128, activation=\"relu\")         self.dense2 = layers.Dense(128, activation=\"relu\")         self.output_action = layers.Dense(action_size, activation=\"softmax\")      def call(self, state):         x = self.dense1(state)         x = self.dense2(x)         return self.output_action(x)  # \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c action_size = 2 # \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0435\u0441\u0442\u044c 2 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f model = SimpleActorModel(action_size)  state = tf.constant([[0.1, 0.2, 0.3]]) # \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b action_probabilities = model(state) print(\"\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439:\", action_probabilities.numpy())<\/code><\/pre>\n<p><code>SimpleActorModel<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0432\u0435\u043a\u0442\u043e\u0440 \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c. \u0417\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u0432\u0430 \u0441\u043a\u0440\u044b\u0442\u044b\u0445 \u0441\u043b\u043e\u044f \u0441 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0435\u0439 ReLU \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u2014 softmax, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/p>\n<h4>Critic <\/h4>\n<p>Critic \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0438\u043b\u0438 \u043f\u043b\u043e\u0445\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 Actor&#8217;\u0430 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0446\u0435\u043b\u0438. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u0440\u0430\u0441\u0447\u0435\u0442\u0430 value function, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u043d\u0430\u0433\u0440\u0430\u0434\u044b, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0435 \u0437\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0441\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. Critic \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0435 \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u0435 \u0430\u0433\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u0432 \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u043e\u0439 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044f \u0432\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Critic \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c TensorFlow:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras import layers  class SimpleCriticModel(tf.keras.Model):     def __init__(self):         super(SimpleCriticModel, self).__init__()         self.dense1 = layers.Dense(128, activation=\"relu\")         self.dense2 = layers.Dense(128, activation=\"relu\")         self.value = layers.Dense(1)      def call(self, state):         x = self.dense1(state)         x = self.dense2(x)         return self.value(x)  # \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f model = SimpleCriticModel()  state = tf.constant([[0.1, 0.2, 0.3]]) # \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b value = model(state) print(\"\u041f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u043d\u0430\u044f \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f:\", value.numpy())<\/code><\/pre>\n<p><code>SimpleCriticModel<\/code> \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0440\u0435\u0434\u044b \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0446\u0435\u043d\u043a\u0443 \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, Critic \u0432\u044b\u0434\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0443\u044e \u043d\u0430\u0433\u0440\u0430\u0434\u0443.<\/p>\n<h2>Actor-Critic \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c<\/h2>\n<p>\u0418 \u0432\u043e\u0442<strong> Actor-Critic<\/strong> \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p>Actor \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u044b.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, Critic \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u0438. \u042d\u0442\u0430 \u043e\u0446\u0435\u043d\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0431\u044b\u043b\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0446\u0435\u043d\u043a\u0438 Critic, Actor \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0432\u043e\u044e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c <em>\u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0432\u043e\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f<\/em> \u043f\u043e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0435, \u0433\u0434\u0435 Actor \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u043c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u0435.<\/p>\n<p>Critic \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u044f\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<p>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 PyTorch:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim  class Actor(nn.Module):     def __init__(self, input_dim, output_dim):         super(Actor, self).__init__()         self.linear = nn.Linear(input_dim, output_dim)          def forward(self, state):         return torch.softmax(self.linear(state), dim=-1)  class Critic(nn.Module):     def __init__(self, input_dim):         super(Critic, self).__init__()         self.linear = nn.Linear(input_dim, 1)          def forward(self, state):         return self.linear(state)  def train(actor, critic, state, action, reward, next_state, done):     optimizer_actor = optim.Adam(actor.parameters(), lr=1e-3)     optimizer_critic = optim.Adam(critic.parameters(), lr=1e-3)          # Critic update     value = critic(state)     next_value = critic(next_state)     td_error = reward + (1 - done) * 0.99 * next_value - value     critic_loss = td_error.pow(2)      optimizer_critic.zero_grad()     critic_loss.backward()     optimizer_critic.step()      # Actor update     log_prob = torch.log(actor(state)[action])     actor_loss = -log_prob * td_error.detach()      optimizer_actor.zero_grad()     actor_loss.backward()     optimizer_actor.step()<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 TensorFlow:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras import layers  class ActorCritic(tf.keras.Model):     def __init__(self, num_actions):         super(ActorCritic, self).__init__()         self.common = layers.Dense(128, activation='relu')         self.actor = layers.Dense(num_actions, activation='softmax')         self.critic = layers.Dense(1)      def call(self, inputs):         x = self.common(inputs)         return self.actor(x), self.critic(x)  model = ActorCritic(num_actions=4) optimizer = tf.keras.optimizers.Adam(lr=0.01)  def train_step(state, action, reward, next_state, done):     with tf.GradientTape() as tape:         action_probs, critic_value = model(state)         _, critic_value_next = model(next_state)         action_log_probs = tf.math.log(action_probs[0, action])         td_error = reward + 0.99 * critic_value_next * (1 - done) - critic_value         actor_loss = -action_log_probs * tf.stop_gradient(td_error)         critic_loss = td_error**2      grads = tape.gradient([actor_loss, critic_loss], model.trainable_variables)     optimizer.apply_gradients(zip(grads, model.trainable_variables))<\/code><\/pre>\n<p>TensorFlow \u0438 Keras \u0441 Functional API:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras.layers import Input, Dense from tensorflow.keras.models import Model  def create_actor(input_shape, output_shape):     inputs = Input(shape=input_shape)     x = Dense(64, activation='relu')(inputs)     outputs = Dense(output_shape, activation='softmax')(x)     model = Model(inputs, outputs)     return model   def create_critic(input_shape):     inputs = Input(shape=input_shape)     x = Dense(64, activation='relu')(inputs)     outputs = Dense(1)(x)     model = Model(inputs, outputs)     return model  actor = create_actor(input_shape=(4,), output_shape=2) critic = create_critic(input_shape=(4,))<\/code><\/pre>\n<p>PyTorch \u0441 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0435\u0438\u043c:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim  class ActorCritic(nn.Module):     def __init__(self, input_dim, action_dim):         super(ActorCritic, self).__init__()         self.common = nn.Linear(input_dim, 64)         self.actor = nn.Linear(64, action_dim)         self.critic = nn.Linear(64, 1)          def forward(self, state):         x = torch.relu(self.common(state))         return torch.softmax(self.actor(x), dim=-1), self.critic(x)  def train(model, state, action, reward, next_state, done):     optimizer = optim.Adam(model.parameters(), lr=5e-4)          # Compute loss     action_probs, value = model(state)     _, next_value = model(next_state)     td_error = reward + (1 - done) * 0.99 * next_value - value     action_log_probs = torch.log(action_probs[action])     actor_loss = -action_log_probs * td_error.detach()     critic_loss = td_error.pow(2)      # Optimize the model     optimizer.zero_grad()     (actor_loss + critic_loss).backward()     optimizer.step()<\/code><\/pre>\n<h4>Advantage Actor-Critic  <\/h4>\n<p>\u0412 Advantage Actor-Critic  \u0430\u043a\u0446\u0435\u043d\u0442 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0435 \u043c\u0435\u0436\u0434\u0443 \u043e\u0446\u0435\u043d\u043a\u043e\u0439 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 actor \u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0446\u0435\u043d\u043a\u043e\u0439 \u044d\u0442\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 critic, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430.<\/p>\n<p><em>(Advantage Function, A(s,a))<\/em> \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439 \u043d\u0430\u0433\u0440\u0430\u0434\u043e\u0439 \u0437\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438 \u0441\u0440\u0435\u0434\u043d\u0435\u0439 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439 \u043d\u0430\u0433\u0440\u0430\u0434\u043e\u0439 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u0424\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, <em>A(s,a) = Q(s,a) &#8212; V(s)<\/em>, \u0433\u0434\u0435 <em>Q(s,a)<\/em> \u2014 \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0430\u044f \u043d\u0430\u0433\u0440\u0430\u0434\u0430 \u0437\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <em>a<\/em> \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 <em>s<\/em>, \u0430 <em>V(s)<\/em> \u2014 \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0430\u044f \u043d\u0430\u0433\u0440\u0430\u0434\u0430 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 <em>s<\/em>, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0430\u044f \u043e\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 actor \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0441\u0440\u0435\u0434\u043d\u0435\u0435, \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<p><strong>Asynchronous Advantage Actor-Critic (A3C)<\/strong>: \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 A2C, \u0433\u0434\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim import numpy as np import threading import gym  class ActorCritic(nn.Module):     def __init__(self, num_inputs, num_actions):         super(ActorCritic, self).__init__()         self.critic = nn.Linear(num_inputs, 1)         self.actor = nn.Linear(num_inputs, num_actions)          def forward(self, x):         value = self.critic(x)         probs = torch.softmax(self.actor(x), dim=-1)         return probs, value  def worker(global_model, optimizer, env_name, global_results, lock, worker_id):     local_model = ActorCritic(num_inputs, num_actions)     local_model.load_state_dict(global_model.state_dict())          env = gym.make(env_name)     state = env.reset()          while True:         # \u043a\u043e\u0434 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u043e\u043c \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438                  with lock:             global_model.load_state_dict(local_model.state_dict())  # \u0433\u043b\u043e\u0431\u0430\u043b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 global_model = ActorCritic(num_inputs, num_actions) optimizer = optim.Adam(global_model.parameters()) workers = [threading.Thread(target=worker, args=(global_model, optimizer, 'CartPole-v1', global_results, lock, i)) for i in range(num_workers)] for w in workers:     w.start() for w in workers:     w.join()<\/code><\/pre>\n<p><strong>Synchronous Advantage Actor-Critic (Synchronous A2C \u0438\u043b\u0438 A2C)<\/strong>: \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 A3C, A2C \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u0440\u0435\u0434\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0442 \u0432\u0441\u0435\u0445 \u0430\u043a\u0442\u043e\u0440\u043e\u0432, \u044d\u0442\u043e \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u0435\u0440\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0434\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u044e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u0445\u043e\u0442\u044f \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim import numpy as np import gym  class ActorCritic(nn.Module):     # \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438 forward \u043c\u0435\u0442\u043e\u0434 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b A3C  def update_global(optimizer, global_model, loss):     optimizer.zero_grad()     loss.backward()     optimizer.step()  env = gym.make('CartPole-v1') global_model = ActorCritic(num_inputs, num_actions) optimizer = optim.Adam(global_model.parameters())  # \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 for episode in range(total_episodes):     state = env.reset()     done = False     while not done:         # \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0438 \u0441\u0431\u043e\u0440 \u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f         loss = compute_loss(...)  # \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0435\u0440\u044c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0438 \u043e\u0446\u0435\u043d\u043e\u043a         update_global(optimizer, global_model, loss)<\/code><\/pre>\n<p><strong>Proximal Policy Optimization (PPO)<\/strong>: \u0445\u043e\u0442\u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u044b\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c A2C, PPO \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u0438 Actor-Critic \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0432\u0432\u043e\u0434\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e\u0442\u0435\u0440\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0435:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim import numpy as np import gym  class ActorCritic(nn.Module):     def __init__(self, num_inputs, num_actions):         super(ActorCritic, self).__init__()         self.critic = nn.Linear(num_inputs, 1)         self.actor = nn.Linear(num_inputs, num_actions)          def forward(self, x):         value = self.critic(x)         probs = torch.softmax(self.actor(x), dim=-1)         return probs, value  def ppo_loss(old_log_probs, new_log_probs, advantages, clip_param=0.2):     ratios = torch.exp(new_log_probs - old_log_probs)     surr1 = ratios * advantages     surr2 = torch.clamp(ratios, 1.0 - clip_param, 1.0 + clip_param) * advantages     return -torch.min(surr1, surr2).mean()  def compute_advantages(rewards, values, gamma=0.99, tau=0.95):     advantages = torch.zeros_like(rewards)     gae = 0     for t in reversed(range(len(rewards))):         delta = rewards[t] + gamma * values[t + 1] - values[t]         gae = delta + gamma * tau * gae         advantages[t] = gae     return advantages  # \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0440\u0435\u0434\u044b, \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 env = gym.make('CartPole-v1') num_inputs = env.observation_space.shape[0] num_actions = env.action_space.n model = ActorCritic(num_inputs, num_actions) optimizer = optim.Adam(model.parameters(), lr=1e-3)  for epoch in range(10):  # \u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u044d\u043f\u043e\u0445 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f     # \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u044b, \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0438 \u0442.\u0434.          # \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043c\u044b \u0443\u0436\u0435 \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445, \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445, \u043d\u0430\u0433\u0440\u0430\u0434\u0430\u0445     # states, actions, rewards, next_states, dones          # \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c\u043e\u0432 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439, \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u0442\u0435\u0440\u044c \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0448\u0430\u0433\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438     old_log_probs = ...  # \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c\u044b \u0441\u0442\u0430\u0440\u044b\u0445 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439     new_log_probs = ...  # \u043b\u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c\u044b \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0438     advantages = ...  # \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430, \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 compute_advantages          loss = ppo_loss(old_log_probs, new_log_probs, advantages)     optimizer.zero_grad()     loss.backward()     optimizer.step()<\/code><\/pre>\n<hr\/>\n<p>\u0412 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0445\u043e\u0447\u0443 \u043f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u0432\u0430\u0441 \u043d\u0430 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0432\u0435\u0431\u0438\u043d\u0430\u0440 \u043f\u0440\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 FinRL \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u043e\u0433\u043e \u0430\u0433\u0435\u043d\u0442\u0430. <a href=\"https:\/\/otus.pw\/8zeT\/\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/799865\/\"> https:\/\/habr.com\/ru\/articles\/799865\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p><em>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<\/em><\/p>\n<p><strong>Actor-Critic<\/strong> \u2014 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0432 RL, \u0441\u0443\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 \u043d\u0430 \u0441\u043b\u043e\u0432\u0430\u0445, \u043e\u043d \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043a\u0430\u043a <em>policy-based<\/em> \u0438 \u043e\u0446\u0435\u043d\u043a\u0438 <em>value-based<\/em>. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043b\u0438\u0446\u0430: <em>Actor<\/em> \u0438 <em>Critic<\/em><strong>. Actor \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0431\u043e\u0440 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439,<\/strong> \u0442.\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b. <strong>Critic \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0438\u043b\u0438 \u043f\u043b\u043e\u0445\u043e Actor \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439<\/strong>, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c \u0447\u0435\u0440\u0435\u0437 \u043e\u0446\u0435\u043d\u043a\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 Actor&#8217;a. <\/p>\n<h4>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 Actor<\/h4>\n<p>Actor \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0431\u043e\u0440 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0433\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b. Actor \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043a\u0430\u043a \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043f\u043f\u0440\u043e\u043a\u0441\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e Actor, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e TensorFlow:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras import layers  class SimpleActorModel(tf.keras.Model):     def __init__(self, action_size):         super(SimpleActorModel, self).__init__()         self.dense1 = layers.Dense(128, activation=\"relu\")         self.dense2 = layers.Dense(128, activation=\"relu\")         self.output_action = layers.Dense(action_size, activation=\"softmax\")      def call(self, state):         x = self.dense1(state)         x = self.dense2(x)         return self.output_action(x)  # \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c action_size = 2 # \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0435\u0441\u0442\u044c 2 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f model = SimpleActorModel(action_size)  state = tf.constant([[0.1, 0.2, 0.3]]) # \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b action_probabilities = model(state) print(\"\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439:\", action_probabilities.numpy())<\/code><\/pre>\n<p><code>SimpleActorModel<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0432\u0435\u043a\u0442\u043e\u0440 \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c. \u0417\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u0432\u0430 \u0441\u043a\u0440\u044b\u0442\u044b\u0445 \u0441\u043b\u043e\u044f \u0441 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0435\u0439 ReLU \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u2014 softmax, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/p>\n<h4>Critic <\/h4>\n<p>Critic \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0438\u043b\u0438 \u043f\u043b\u043e\u0445\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 Actor&#8217;\u0430 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0446\u0435\u043b\u0438. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u0440\u0430\u0441\u0447\u0435\u0442\u0430 value function, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u043d\u0430\u0433\u0440\u0430\u0434\u044b, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0435 \u0437\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0441\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. Critic \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0435 \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u0435 \u0430\u0433\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u0432 \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u043e\u0439 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044f \u0432\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Critic \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c TensorFlow:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras import layers  class SimpleCriticModel(tf.keras.Model):     def __init__(self):         super(SimpleCriticModel, self).__init__()         self.dense1 = layers.Dense(128, activation=\"relu\")         self.dense2 = layers.Dense(128, activation=\"relu\")         self.value = layers.Dense(1)      def call(self, state):         x = self.dense1(state)         x = self.dense2(x)         return self.value(x)  # \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f model = SimpleCriticModel()  state = tf.constant([[0.1, 0.2, 0.3]]) # \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u044b value = model(state) print(\"\u041f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u043d\u0430\u044f \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f:\", value.numpy())<\/code><\/pre>\n<p><code>SimpleCriticModel<\/code> \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0440\u0435\u0434\u044b \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0446\u0435\u043d\u043a\u0443 \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, Critic \u0432\u044b\u0434\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0443\u044e \u043d\u0430\u0433\u0440\u0430\u0434\u0443.<\/p>\n<h2>Actor-Critic \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c<\/h2>\n<p>\u0418 \u0432\u043e\u0442<strong> Actor-Critic<\/strong> \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p>Actor \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u044b.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, Critic \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u0438. \u042d\u0442\u0430 \u043e\u0446\u0435\u043d\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0431\u044b\u043b\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0446\u0435\u043d\u043a\u0438 Critic, Actor \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0432\u043e\u044e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c <em>\u0433\u0440\u0430\u0434\u0438\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0432\u043e\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f<\/em> \u043f\u043e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0435, \u0433\u0434\u0435 Actor \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u043c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u0435.<\/p>\n<p>Critic \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0432\u043e\u0437\u043d\u0430\u0433\u0440\u0430\u0436\u0434\u0435\u043d\u0438\u044f\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<p>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 PyTorch:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim  class Actor(nn.Module):     def __init__(self, input_dim, output_dim):         super(Actor, self).__init__()         self.linear = nn.Linear(input_dim, output_dim)          def forward(self, state):         return torch.softmax(self.linear(state), dim=-1)  class Critic(nn.Module):     def __init__(self, input_dim):         super(Critic, self).__init__()         self.linear = nn.Linear(input_dim, 1)          def forward(self, state):         return self.linear(state)  def train(actor, critic, state, action, reward, next_state, done):     optimizer_actor = optim.Adam(actor.parameters(), lr=1e-3)     optimizer_critic = optim.Adam(critic.parameters(), lr=1e-3)          # Critic update     value = critic(state)     next_value = critic(next_state)     td_error = reward + (1 - done) * 0.99 * next_value - value     critic_loss = td_error.pow(2)      optimizer_critic.zero_grad()     critic_loss.backward()     optimizer_critic.step()      # Actor update     log_prob = torch.log(actor(state)[action])     actor_loss = -log_prob * td_error.detach()      optimizer_actor.zero_grad()     actor_loss.backward()     optimizer_actor.step()<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 TensorFlow:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras import layers  class ActorCritic(tf.keras.Model):     def __init__(self, num_actions):         super(ActorCritic, self).__init__()         self.common = layers.Dense(128, activation='relu')         self.actor = layers.Dense(num_actions, activation='softmax')         self.critic = layers.Dense(1)      def call(self, inputs):         x = self.common(inputs)         return self.actor(x), self.critic(x)  model = ActorCritic(num_actions=4) optimizer = tf.keras.optimizers.Adam(lr=0.01)  def train_step(state, action, reward, next_state, done):     with tf.GradientTape() as tape:         action_probs, critic_value = model(state)         _, critic_value_next = model(next_state)         action_log_probs = tf.math.log(action_probs[0, action])         td_error = reward + 0.99 * critic_value_next * (1 - done) - critic_value         actor_loss = -action_log_probs * tf.stop_gradient(td_error)         critic_loss = td_error**2      grads = tape.gradient([actor_loss, critic_loss], model.trainable_variables)     optimizer.apply_gradients(zip(grads, model.trainable_variables))<\/code><\/pre>\n<p>TensorFlow \u0438 Keras \u0441 Functional API:<\/p>\n<pre><code class=\"python\">import tensorflow as tf from tensorflow.keras.layers import Input, Dense from tensorflow.keras.models import Model  def create_actor(input_shape, output_shape):     inputs = Input(shape=input_shape)     x = Dense(64, activation='relu')(inputs)     outputs = Dense(output_shape, activation='softmax')(x)     model = Model(inputs, outputs)     return model   def create_critic(input_shape):     inputs = Input(shape=input_shape)     x = Dense(64, activation='relu')(inputs)     outputs = Dense(1)(x)     model = Model(inputs, outputs)     return model  actor = create_actor(input_shape=(4,), output_shape=2) critic = create_critic(input_shape=(4,))<\/code><\/pre>\n<p>PyTorch \u0441 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0435\u0438\u043c:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim  class ActorCritic(nn.Module):     def __init__(self, input_dim, action_dim):         super(ActorCritic, self).__init__()         self.common = nn.Linear(input_dim, 64)         self.actor = nn.Linear(64, action_dim)         self.critic = nn.Linear(64, 1)          def forward(self, state):         x = torch.relu(self.common(state))         return torch.softmax(self.actor(x), dim=-1), self.critic(x)  def train(model, state, action, reward, next_state, done):     optimizer = optim.Adam(model.parameters(), lr=5e-4)          # Compute loss     action_probs, value = model(state)     _, next_value = model(next_state)     td_error = reward + (1 - done) * 0.99 * next_value - value     action_log_probs = torch.log(action_probs[action])     actor_loss = -action_log_probs * td_error.detach()     critic_loss = td_error.pow(2)      # Optimize the model     optimizer.zero_grad()     (actor_loss + critic_loss).backward()     optimizer.step()<\/code><\/pre>\n<h4>Advantage Actor-Critic  <\/h4>\n<p>\u0412 Advantage Actor-Critic  \u0430\u043a\u0446\u0435\u043d\u0442 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0435 \u043c\u0435\u0436\u0434\u0443 \u043e\u0446\u0435\u043d\u043a\u043e\u0439 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 actor \u0438 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0446\u0435\u043d\u043a\u043e\u0439 \u044d\u0442\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 critic, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430.<\/p>\n<p><em>(Advantage Function, A(s,a))<\/em> \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439 \u043d\u0430\u0433\u0440\u0430\u0434\u043e\u0439 \u0437\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438 \u0441\u0440\u0435\u0434\u043d\u0435\u0439 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439 \u043d\u0430\u0433\u0440\u0430\u0434\u043e\u0439 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u0424\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, <em>A(s,a) = Q(s,a) &#8212; V(s)<\/em>, \u0433\u0434\u0435 <em>Q(s,a)<\/em> \u2014 \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0430\u044f \u043d\u0430\u0433\u0440\u0430\u0434\u0430 \u0437\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <em>a<\/em> \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 <em>s<\/em>, \u0430 <em>V(s)<\/em> \u2014 \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0430\u044f \u043d\u0430\u0433\u0440\u0430\u0434\u0430 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 <em>s<\/em>, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0430\u044f \u043e\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 actor \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0441\u0440\u0435\u0434\u043d\u0435\u0435, \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<p><strong>Asynchronous Advantage Actor-Critic (A3C)<\/strong>: \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 A2C, \u0433\u0434\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">import torch import torch.nn as nn import torch.optim as optim import numpy as np import threading import gym  class ActorCritic(nn.Module):     def __init__(self, num_inputs, num_actions):         super(ActorCritic, self).__init__()         self.critic = nn.Linear(num_inputs, 1)         self.actor = nn.Linear(num_inputs, num_actions)          def forward(self, x):         value = self.critic(x)         probs = torch.softmax(self.actor(x), dim=-1)         return probs, value  def worker(global_model, optimizer, env_name, global_results, lock, worker_id):     local_model = ActorCritic(num_inputs, num_actions)     local_model.load_state_dict(global_model.state_dict())          env = gym.make(env_name)     state = env.reset()          while True:         # \u043a\u043e\u0434 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0430\u0433\u0435\u043d\u0442\u043e\u043c \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438                  with lock:<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-370658","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370658","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=370658"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370658\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=370658"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=370658"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=370658"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}