[英]How do i correctly communicate with a ftdi f232rl module via python?
[英]RL + optimization: how to do it better?
我正在學習如何使用強化學習進行優化。 我選擇了二部圖中的最大匹配問題,因為我可以很容易地計算出真正的最優值。
回想一下,圖中的匹配是邊的子集,其中沒有兩條邊入射在同一節點/頂點上。 目標是找到最大的此類子集。
我在下面展示了我的完整代碼,但首先讓我解釋一下它的一部分。
num_variables = 1000
g = ig.Graph.Random_Bipartite(num_variables, num_variables, p=3/num_variables)
g_matching = g.maximum_bipartite_matching()
print("Matching size", len([v for v in g_matching.matching if v < num_variables and v != -1]))
這將生成一個隨機二分圖,在兩組節點中的每一組中都有 1000 個節點。 然后它打印出真正的最大匹配的大小。
在下面的代碼中, self.agent_pos
是一個數組,表示當前找到的匹配項。 它的長度是原始圖中的邊數,如果包含邊i
,則索引i
為 1,否則為 0。 self.matching
是增長匹配中的邊集。 self.matching_nodes
是增長匹配中的一組節點,用於檢查是否可以添加特定邊。
import igraph as ig
from tqdm import tqdm
import numpy as np
import gym
from gym import spaces
from stable_baselines3 import PPO
from stable_baselines3.common.env_util import make_vec_env
class MaxMatchEnv(gym.Env):
metadata = {'render.modes': ['console']}
def __init__(self, array_length=10):
super(MaxMatchEnv, self).__init__()
# Size of the 1D-grid
self.array_length = array_length
self.agent_pos = [0]*array_length
self.action_space = spaces.Discrete(array_length)
self.observation_space = spaces.Box(low=0, high=1, shape=(array_length,), dtype=np.uint8)
self.matching = set() # set of edges
self.matching_nodes = set() # set of node ids (ints)
self.matching_size = len([v for v in g_matching.matching if v < num_variables and v != -1])
self.best_found = 0
def reset(self):
# Initialize the array to have random values
self.time = 0
#print(self.agent_pos)
self.agent_pos = [0]*self.array_length
self.matching = set()
self.matching_nodes = set()
return np.array(self.agent_pos)
def step(self, action):
self.time += 1
reward = 0
edge = g.es[action]
if not(edge.source in self.matching_nodes or edge.target in self.matching_nodes):
self.matching.add(edge)
self.matching_nodes.add(edge.source)
self.matching_nodes.add(edge.target)
self.agent_pos[action] = 1
if sum(self.agent_pos) > self.best_found:
self.best_found = sum(self.agent_pos)
print("New max", self.best_found)
reward = 1
elif self.agent_pos[action] == 1:
#print("Removing edge", action)
self.matching_nodes.remove(edge.source)
self.matching_nodes.remove(edge.target)
self.matching.remove(edge)
self.agent_pos[action] = 0
reward = -1
done = sum(self.agent_pos) == self.matching_size
info = {}
return np.array(self.agent_pos), reward, done, info
def render(self, mode='console'):
print(sum(self.agent_pos))
def close(self):
pass
if __name__ == '__main__':
num_variables = 1000
g = ig.Graph.Random_Bipartite(num_variables, num_variables, p=3/num_variables)
g_matching = g.maximum_bipartite_matching()
print("Matching size", len([v for v in g_matching.matching if v < num_variables and v != -1]))
env = make_vec_env(lambda: MaxMatchEnv(array_length=len(g.es)), n_envs=12)
model = PPO('MlpPolicy', env, verbose=1).learn(10000000)
這有很多問題,但最主要的是它沒有很好地優化。 這段代碼給出了 550 以上,然后在真正的最佳值超過 900 時停止改進(它由代碼在開始時打印出來)。
主要問題是:
如何才能做得更好,以便更好地匹配?
一個附屬問題是,如何打印迄今為止找到的最佳匹配? 我嘗試使用 self.best_found 來保持最好的分數是行不通的,因為它似乎會定期重置。
沒有幫助的改變
done
為 True。變化如下:
if self.time == 1000:
done = True
else:
done = False
添加print(max(env.get_attr("best_found")))
代替print("New max", self.best_found)
對done
的更改完全沒有顯示任何優勢。
要打印每個環境的最大值,您可以使用來自穩定基線的get_attr
方法。 更多信息在他們的官方文檔中。
例如,下面的行將打印 12 個環境中每個環境的最大值,然后是所有環境的最大值。
print(env.get_attr("best_found"))
print(max(env.get_attr("best_found")))
至於為什么它不收斂,可能是因為選擇了錯誤的獎勵,盡管從你的獎勵選擇來看它似乎是明智的。 我在你的代碼中添加了一個調試打印,看看是否有一些步驟導致done = True
,但似乎環境永遠不會達到 state。我認為對於 model 來說,有多個動作序列會導致帶有done = True
的 state,這意味着 model 將經歷一集的結尾。 我沒有詳細研究您代碼中的問題,但也許這些信息可以幫助調試您的問題。
如果我們將問題與CartPole等其他環境進行比較,我們有以done = True
結尾的劇集,這有助於 model 學習更好的策略(在您的情況下,您可以限制每集的動作數量,而不是永遠運行同一集). 這可以幫助 model 避免陷入局部最優,因為你給它機會在新的情節中“重試”。
如果我沒看錯,那么您沒有執行任何超參數調整。 你怎么知道你的學習率/策略更新率/任何其他可變參數是否適合手頭的問題?
看起來穩定基線內置了這個功能: https://stable-baselines.readthedocs.io/en/master/guide/rl_zoo.html?highlight=tune#hyperparameter-optimization
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.