案例:從CartPole-v1遷移到MountainCar-v0
- 在源環境(CartPole-v1)中訓練模型
首先,我們使用DQN算法在CartPole-v1環境中訓練一個強化學習模型。以下是代碼示例:
import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import random
from collections import deque# 定義 Q 網絡
class QNetwork(nn.Module):def __init__(self, state_dim, action_dim):super(QNetwork, self).__init__()self.fc1 = nn.Linear(state_dim, 128)self.fc2 = nn.Linear(128, 128)self.fc3 = nn.Linear(128, action_dim)def forward(self, x):x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))return self.fc3(x)# Replay buffer,用于存儲經驗
class ReplayBuffer:def __init__(self, capacity):self.buffer = deque(maxlen=capacity)def add(self, transition):self.buffer.append(transition)def sample(self, batch_size):transitions = random.sample(self.buffer, batch_size)states, actions, rewards, next_states, dones = zip(*transitions)states = np.stack(states)next_states = np.stack(next_states)actions = np.array(actions, dtype=np.int64)rewards = np.array(rewards, dtype=np.float32)dones = np.array(dones, dtype=np.float32)return states, actions, rewards, next_states, donesdef size(self):return len(self.buffer)# 選擇動作
def select_action(state, policy_net, epsilon, action_dim):if random.random() < epsilon:return random.choice(np.arange(action_dim))else:with torch.no_grad():state = torch.FloatTensor(state).unsqueeze(0)q_values = policy_net(state)return q_values.argmax().item()# Q-learning 更新
def update_model(policy_net, target_net, optimizer, replay_buffer, batch_size, gamma):if replay_buffer.size() < batch_size:returnstates, actions, rewards, next_states, dones = replay_buffer.sample(batch_size)states = torch.FloatTensor(states)actions = torch.LongTensor(actions)rewards = torch.FloatTensor(rewards)next_states = torch.FloatTensor(next_states)dones = torch.FloatTensor(dones)q_values = policy_net(states).gather(1, actions.unsqueeze(1)).squeeze(1)next_q_values = target_net(next_states).max(1)[0]target_q_values = rewards + gamma * next_q_values * (1 - dones)loss = (q_values - target_q_values.detach()).pow(2).mean()optimizer.zero_grad()loss.backward()optimizer.step()# 訓練模型
def train_dqn(env_name, num_episodes=500, gamma=0.99, epsilon_start=1.0, epsilon_end=0.01, epsilon_decay=0.995, batch_size=64):env = gym.make(env_name)state_dim = env.observation_space.shape[0]action_dim = env.action_space.npolicy_net = QNetwork(state_dim, action_dim)target_net = QNetwork(state_dim, action_dim)target_net.load_state_dict(policy_net.state_dict())target_net.eval()optimizer = optim.Adam(policy_net.parameters())replay_buffer = ReplayBuffer(10000)epsilon = epsilon_startfor episode in range(num_episodes):state, _ = env.reset()total_reward = 0while True:action = select_action(state, policy_net, epsilon, action_dim)next_state, reward, done, _, __ = env.step(action)replay_buffer.add((state, action, reward, next_state, done))state = next_statetotal_reward += rewardupdate_model(policy_net, target_net, optimizer, replay_buffer, batch_size, gamma)if done:print(f"Episode {episode + 1}/{num_episodes}, Total Reward: {total_reward}")breakepsilon = max(epsilon_end, epsilon_decay * epsilon)if episode % 10 == 0:target_net.load_state_dict(policy_net.state_dict())return policy_net# 在源環境(CartPole)中訓練模型
policy_net_cartpole = train_dqn(env_name='CartPole-v1')
接下來,我們將CartPole-v1環境中訓練好的模型遷移到MountainCar-v0環境中,并進行微調。以下是代碼示例:
# 定義函數以匹配網絡的結構,進行部分權重的遷移
def transfer_weights(policy_net, target_env_state_dim, target_env_action_dim):# 獲取預訓練的網絡pretrained_dict = policy_net.state_dict()# 創建新網絡,適應目標環境的狀態和動作維度new_policy_net = QNetwork(target_env_state_dim, target_env_action_dim)# 獲取新網絡的權重new_dict = new_policy_net.state_dict()# 僅保留在預訓練網絡和新網絡中都有的層(即隱藏層的參數)pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in new_dict and 'fc1' not in k and 'fc3' not in k}# 更新新網絡的權重new_dict.update(pretrained_dict)# 將更新后的字典加載到新模型中new_policy_net.load_state_dict(new_dict)return new_policy_net# 微調模型
def fine_tune_dqn(policy_net, env_name, num_episodes=200, gamma=0.99, epsilon_start=0.1, epsilon_end=0.01, epsilon_decay=0.995, batch_size=64):env = gym.make(env_name)target_state_dim = env.observation_space.shape[0]target_action_dim = env.action_space.n# 調用 transfer_weights 函數,將權重從 CartPole 模型遷移到新的 MountainCar 模型policy_net = transfer_weights(policy_net, target_state_dim, target_action_dim)target_net = QNetwork(target_state_dim, target_action_dim)target_net.load_state_dict(policy_net.state_dict())target_net.eval()optimizer = optim.Adam(policy_net.parameters())replay_buffer = ReplayBuffer(10000)epsilon = epsilon_startfor episode in range(num_episodes):state, _ = env.reset()total_reward = 0while True:action = select_action(state, policy_net, epsilon, target_action_dim)next_state, reward, done, _, __ = env.step(action)replay_buffer.add((state, action, reward, next_state, done))state = next_statetotal_reward += rewardupdate_model(policy_net, target_net, optimizer, replay_buffer, batch_size, gamma)if done:print(f"Episode {episode + 1}/{num_episodes}, Total Reward: {total_reward}")breakepsilon = max(epsilon_end, epsilon_decay * epsilon)if episode % 10 == 0:target_net.load_state_dict(policy_net.state_dict())return policy_net# 微調源環境訓練的策略網絡到目標環境 MountainCar
fine_tuned_policy_net = fine_tune_dqn(policy_net_cartpole, env_name='MountainCar-v0')
強學遷移中哪些沒有變?
在強化學習的遷移學習過程中,即使經過微調,也存在一些保持不變的部分,這些部分是遷移學習能夠有效工作的關鍵。以下是保持不變的主要內容:
-
隱藏層的結構和部分權重
在遷移學習中,通常會保留預訓練模型的隱藏層結構和部分權重。這些隱藏層在源任務中已經學習到了一些通用的特征表示,這些特征在目標任務中可能仍然有用。例如:隱藏層的權重:在預訓練模型中,隱藏層的權重已經通過大量的數據訓練得到了優化。這些權重在遷移到新任務時會被保留,作為新模型的初始化權重。雖然在微調過程中這些權重可能會發生一些變化,但它們的初始值仍然是預訓練模型中的值。
隱藏層的結構:隱藏層的結構(如層數、每層的神經元數量等)通常保持不變,因為這些結構在源任務中已經被證明是有效的。 -
學習算法和框架
遷移學習過程中,學習算法和整體框架通常保持不變。這意味著:算法類型:使用的強化學習算法(如DQN、PPO等)在遷移過程中保持不變。這是因為算法的核心思想和機制適用于多個任務。
框架和超參數:雖然某些超參數(如學習率、折扣因子等)可能需要根據新任務進行調整,但整體的算法框架和大部分超參數保持不變。 -
通用的特征表示
隱藏層學習到的特征表示在遷移過程中保持相對穩定。這些特征表示是數據的通用特征,能夠在多個任務中發揮作用。例如:低級特征:在視覺任務中,卷積神經網絡的低級層通常學習到邊緣、紋理等通用特征,這些特征在不同的視覺任務中都可能有用。
狀態空間的通用表示:在強化學習中,隱藏層可能學習到狀態空間的通用表示,這些表示在不同的任務中仍然可以提供有用的信息。 -
目標函數的形式
雖然具體的目標函數(如獎勵函數)可能因任務而異,但目標函數的形式通常保持不變。強化學習的目標是最大化累積獎勵,這一目標形式在遷移學習中仍然適用。例如:最大化累積獎勵:無論是源任務還是目標任務,強化學習的目標都是通過學習策略來最大化累積獎勵。這一目標形式在遷移過程中保持不變。
獎勵函數的形式:雖然獎勵的具體定義可能不同,但獎勵函數的形式(如即時獎勵與累積獎勵的關系)通常保持一致。 -
交互機制
強化學習的核心是通過與環境的交互來學習策略。這種交互機制在遷移學習中保持不變:環境交互:在源任務和目標任務中,智能體都需要通過與環境的交互來獲取反饋(如獎勵和狀態轉移)。這種交互機制在遷移過程中保持一致。
探索與利用的平衡:在遷移學習中,智能體仍然需要在探索新的策略和利用已知的策略之間進行平衡。這種平衡機制在遷移過程中保持不變。 -
策略網絡的輸出層結構
雖然輸出層的權重可能會根據目標任務進行調整,但輸出層的結構(如輸出維度)通常保持不變。這是因為輸出層的結構是由任務的性質決定的,例如動作空間的維度。
舉例說明
假設我們在CartPole-v1環境中訓練了一個DQN模型,并將其遷移到MountainCar-v0環境中進行微調。以下是保持不變的部分:隱藏層結構和部分權重:隱藏層的結構和部分權重從CartPole-v1模型遷移到MountainCar-v0模型中。
DQN算法框架:使用的DQN算法框架保持不變,包括經驗回放、目標網絡等機制。
通用特征表示:隱藏層學習到的通用特征表示(如狀態的低級特征)在MountainCar-v0環境中仍然有用。
目標函數形式:最大化累積獎勵的目標函數形式保持不變。
交互機制:智能體通過與環境的交互來學習策略的機制保持不變。
通過保持這些部分不變,強化學習的遷移學習能夠利用預訓練模型的經驗,加速在新任務中的學習過程,并提高學習效率和性能。