强化学习算法系列(五):最主流的算法框架——Actor-Critic算法框架

news2025/4/19 23:33:19

强化学习算法

(一)动态规划方法——策略迭代算法(PI)和值迭代算法(VI)
(二)Model-Free类方法——蒙特卡洛算法(MC)和时序差分算法(TD)
(三)基于动作值的算法——Sarsa算法与Q-Learning算法
(四)深度强化学习时代的到来——DQN算法
(五)最主流的算法框架——Actor-Critic算法框架
(六)应用最广泛的算法——PPO算法
(七)更高级的算法——DDPG算法与TD3算法
(八)待续


文章目录

  • 强化学习算法
  • 前言
  • 一、REINFORCE算法
    • 1. 核心原理
    • 2. 代码实现
  • 二、Actor-Critic算法框架
    • 1. AC算法的核心思想
    • 2.AC算法代码实现


前言

在以往学习的算法中,我们均围绕状态价值或动作价值间接优化策略,本章开始我们将学习一类新的算法——策略梯度算法,这种算法通过直接优化策略函数得到最优策略。该类算法更强调实用性是,不需要认识每个状态的价值,直接得到最优策略。在本章我们将从最基本的策略梯度算法REINFORCE开始介绍,然后介绍现今强化学习领域最流行的算法框架Actor-Critic算法框架。


一、REINFORCE算法

1. 核心原理

我们从最原始的策略梯度算法——REINFORCE算法开始学习,REINFORCE算法接优化策略函数(Policy),而不是像DQN那样先学值函数再推导策略。
假设你训练一只小狗做动作(坐下、握手):

  • ​DQN方式:先告诉它每个动作的“潜在奖励”,再让它选奖励最高的动作。
  • ​策略梯度:直接告诉它“某个动作做得很好,以后要多做”,通过试错直接调整动作概率。

下面我们通过推导的形式得到REINFORCE算法的核心公式:
策略梯度定理的核心目标是通过梯度上升优化策略参数 θ θ θ,最大化期望回报 J ( θ ) = E [ ∑ t = 0 ∞ γ t r t ] J(\theta )=\mathbb{E}[ {\textstyle \sum_{t=0}^{\infty }}γ^t r_t] J(θ)=E[t=0γtrt]
J ( θ ) J(\theta ) J(θ)写成如下形式
J ( θ ) = ∫ P ( τ ; θ ) R ( τ ) d τ J(\theta )=\int P(\tau;\theta)R(\tau)d\tau J(θ)=P(τ;θ)R(τ)dτ其中,积分符号表示连续环境下对所有可能的取值进行加权平均。 P ( τ ; θ ) P(\tau;\theta) P(τ;θ)为生成某条轨迹的概率,可以将其拆解为 P ( τ ; θ ) = ∏ t = 0 T π ( a t ∣ s t ; θ ) ⋅ P ( s t + 1 ∣ s t , a t ) P(\tau;\theta)={\textstyle \prod_{t=0}^{T}}\pi(a_t|s_t;\theta)\cdot P(s_{t+1}|s_t,a_t) P(τ;θ)=t=0Tπ(atst;θ)P(st+1st,at),也就是策略与状态转移矩阵的概率乘积。 R ( τ ) R(\tau) R(τ)表示该条轨迹获得的奖励值之和。我们以上述形式做为目标函数,并对其求导得到
∇ θ J ( θ ) = ∫ ∇ θ P ( τ ; θ ) R ( τ ) d τ \nabla _\theta J(\theta )=\int \nabla _\theta P(\tau;\theta)R(\tau)d\tau θJ(θ)=θP(τ;θ)R(τ)dτ这里我们再对 ∇ θ P ( τ ; θ ) \nabla _\theta P(\tau;\theta) θP(τ;θ)利用对数微分技巧,得到
∇ θ ln ⁡ P ( τ ; θ ) = ∇ θ P ( τ ; θ ) P ( τ ; θ ) \nabla _\theta \ln P(\tau;\theta)=\frac{\nabla _\theta P(\tau;\theta)}{P(\tau;\theta)} θlnP(τ;θ)=P(τ;θ)θP(τ;θ)因此, ∇ θ P ( τ ; θ ) = ∇ θ ln ⁡ P ( τ ; θ ) ⋅ P ( τ ; θ ) \nabla _\theta P(\tau;\theta)=\nabla _\theta \ln P(\tau;\theta) \cdot P(\tau;\theta) θP(τ;θ)=θlnP(τ;θ)P(τ;θ),代入原式得到
∇ θ J ( θ ) = ∫ ∇ θ ln ⁡ P ( τ ; θ ) R ( τ ) d τ \nabla _\theta J(\theta )=\int \nabla _\theta \ln P(\tau;\theta) R(\tau)d\tau θJ(θ)=θlnP(τ;θ)R(τ)dτ P ( τ ; θ ) = ∏ t = 0 T π ( a t ∣ s t ; θ ) ⋅ P ( s t + 1 ∣ s t , a t ) P(\tau;\theta)={\textstyle \prod_{t=0}^{T}}\pi(a_t|s_t;\theta)\cdot P(s_{t+1}|s_t,a_t) P(τ;θ)=t=0Tπ(atst;θ)P(st+1st,at),去掉其中与 θ \theta θ无关的项得到下式 ∇ θ J ( θ ) = E [ R ( τ ) ∑ t = 0 T ∇ θ ln ⁡ π ( a t ∣ s t ; θ ) ] \nabla _\theta J(\theta )=\mathbb{E}[R(\tau)\sum_{t=0}^{T} \nabla _\theta \ln\pi(a_t|s_t;\theta)] θJ(θ)=E[R(τ)t=0Tθlnπ(atst;θ)]不同的策略梯度算法对上述梯度的计算方式不同,REINFORCE算法通过采样 N 条轨迹来近似期望值:
∇ θ J ( θ ) ≈ 1 N ∑ i = 1 N [ R ( τ i ) ∑ t = 0 T ∇ θ ln ⁡ π ( a i , t ∣ s i , t ; θ ) ] \nabla _\theta J(\theta )\approx\frac{1}N{}\sum_{i=1}^N[R(\tau_i)\sum_{t=0}^{T} \nabla _\theta \ln\pi(a_{i,t}|s_{i,t};\theta)] θJ(θ)N1i=1N[R(τi)t=0Tθlnπ(ai,tsi,t;θ)]因此,REINFORCE算法每个轮次的梯度上升公式可以表示为:
θ ← θ + α ⋅ γ t G t ⋅ ∇ θ log ⁡ π ( a t ∣ s t ; θ ) \theta ←\theta+α\cdotγ^tG_t\cdot\nabla _\theta\log\pi(a_t|s_t;\theta) θθ+αγtGtθlogπ(atst;θ)

这里的 G t G_t Gt就是AC算法中Actor网络更新的核心要点了, G t G_t Gt可以变成多种形式,若换为TD Error
就成了经典AC算法的Actor更新公式;若换为 A t = Q t − A t A_t=Q_t-A_t At=QtAt,则是以优势函数为基础的A2C算法。


2. 代码实现

REINFPRCE算法的实现如下

import gym
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from collections import deque
import random

# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = [
    'SimHei',  # 中易黑体 (Windows)
    'Microsoft YaHei',  # 微软雅黑 (Windows)
    'WenQuanYi Zen Hei',  # 文泉驿正黑 (Linux)
    'Arial Unicode MS'  # macOS
]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 超参数设置
GAMMA = 0.99  # 折扣因子
LR = 0.001  # 学习率
HIDDEN_SIZE = 128  # 网络隐藏层大小
reward_list = []

# 定义设备(自动检测GPU可用性)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


# 定义策略网络结构
class PolicyNetwork(nn.Module):
    def __init__(self, state_dim, action_dim):
        super(PolicyNetwork, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(state_dim, HIDDEN_SIZE),
            nn.ReLU(),
            nn.Linear(HIDDEN_SIZE, action_dim),
            nn.Softmax(dim=-1)  # 输出动作概率
        )

    def forward(self, x):
        return self.fc(x)


# REINFORCE智能体
class REINFORCEAgent:
    def __init__(self, state_dim, action_dim):
        self.action_dim = action_dim

        # 策略网络
        self.policy_net = PolicyNetwork(state_dim, action_dim).to(device)
        self.optimizer = optim.Adam(self.policy_net.parameters(), lr=LR)

        # 存储回合数据的缓冲区
        self.states = []
        self.actions = []
        self.rewards = []

    def choose_action(self, state):
        """ 根据策略网络采样动作 """
        state_tensor = torch.FloatTensor(state).to(device)
        probs = self.policy_net(state_tensor)
        action_dist = torch.distributions.Categorical(probs)
        action = action_dist.sample().item()
        return action

    def store_transition(self, state, action, reward):
        """ 存储回合数据 """
        self.states.append(state)
        self.actions.append(action)
        self.rewards.append(reward)

    def update_model(self):
        """ 使用完整回合数据更新策略 """
        # 计算每个时间步的折扣回报
        returns = []
        G = 0
        for r in reversed(self.rewards):
            G = r + GAMMA * G
            returns.insert(0, G)

        # 转换为张量
        states = torch.FloatTensor(np.array(self.states)).to(device)
        actions = torch.LongTensor(self.actions).to(device)
        returns = torch.FloatTensor(returns).to(device)

        # 归一化回报(减少方差)
        returns = (returns - returns.mean()) / (returns.std() + 1e-9)

        # 计算策略梯度
        probs = self.policy_net(states)
        # 计算log π(a_t|s_t;θ)
        log_probs = torch.log(probs.gather(1, actions.unsqueeze(1)))
        loss = -(log_probs.squeeze() * returns).mean()

        # 梯度下降
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()

        # 清空回合数据
        self.states = []
        self.actions = []
        self.rewards = []


# 训练流程
def train_reinforce(env_name, episodes):
    env = gym.make(env_name)
    state_dim = env.observation_space.shape[0]
    action_dim = env.action_space.n

    agent = REINFORCEAgent(state_dim, action_dim)

    for episode in range(episodes):
        state = env.reset()[0]
        episode_reward = 0
        done = False

        while not done:
            # 1. 选择并执行动作
            action = agent.choose_action(state)
            next_state, reward, terminated, truncated, _ = env.step(action)
            done = terminated or truncated

            # 2. 存储转移数据
            agent.store_transition(state, action, reward)

            state = next_state
            episode_reward += reward

        # 3. 使用完整回合数据更新策略
        agent.update_model()

        # 记录训练进度
        reward_list.append(episode_reward)
        if (episode + 1) % 10 == 0:
            print(f"Episode: {episode + 1}, Reward: {episode_reward}")

    env.close()


if __name__ == "__main__":
    env_name = "CartPole-v1"
    episodes = 2000
    train_reinforce(env_name, episodes)
    np.save(f"result/REINFORCE_rewards.npy", np.array(reward_list))
    plt.plot(range(episodes), reward_list)
    plt.xlabel('迭代次数')
    plt.ylabel('每代的总奖励值')
    plt.title('REINFORCE的训练过程')
    plt.grid(True)
    plt.show()

算法对比绘图代码

import numpy as np
import matplotlib.pyplot as plt

# 加载数据(注意路径与图中一致)
dqn_rewards = np.load("dqn_rewards.npy")
REFINORCE_rewards = np.load("REINFORCE_rewards.npy")
plt.figure(figsize=(12, 6))

# 绘制原始曲线
plt.plot(dqn_rewards, alpha=0.3, color='blue', label='DQN (原始)')
plt.plot(REFINORCE_rewards, alpha=0.3, color='cyan', label='REINFORCE (原始)')

# 绘制滚动平均曲线(窗口大小=50)
window_size = 50
plt.plot(np.convolve(dqn_rewards, np.ones(window_size)/window_size, mode='valid'),
         linewidth=2, color='navy', label='DQN (50轮平均)')
plt.plot(np.convolve(REFINORCE_rewards, np.ones(window_size)/window_size, mode='valid'),

# 图表标注
plt.xlabel('训练轮次 (Episodes)', fontsize=12, fontfamily='SimHei')
plt.ylabel('奖励值', fontsize=12, fontfamily='SimHei')
plt.title('DQN Vs REFINFORCE 训练对比 (CartPole-v1)', fontsize=14, fontfamily='SimHei')
plt.legend(loc='upper left', prop={'family': 'SimHei'})
plt.grid(True, alpha=0.3)

# 保存图片(解决原图未保存的问题)
# plt.savefig('comparison.png', dpi=300, bbox_inches='tight')
plt.show()

算法运行结果及对比:
在这里插入图片描述


二、Actor-Critic算法框架

1. AC算法的核心思想

Actor-Critic(演员-评论家)算法框架当前强化学习算法中最流行的算法框架,这种算法框架融合了值函数近似与策略梯度两种算法的核心思想,后续的PPO、SAC、DDPG等算法均是在此框架下提出的。这里我们首先介绍一下最经典的AC算法核心思想。

Actor-Critic算法结合了策略梯度(Actor)和值函数近似(Critic)其中:

  • ​Actor:策略网络 π ( a ∣ s ; θ ) π(a∣s;θ) π(as;θ),负责生成动作。
  • ​Critic:价值网络 V ( s ; ϕ ) V(s;ϕ) V(s;ϕ)(或 Q ( s , a ; ϕ ) Q(s,a;ϕ) Q(s,a;ϕ)),评估状态或动作的价值,提供策略优化的方向引导。

Actor根据Critic的评估结果调整策略;Critic通过环境反馈优化价值估计。
下面介绍他们的核心更新公式。

  1. Critic的更新(值函数估计)
    经典AC算法中的 Critic网络通过最小化时序差分误差(TD Error)优化函数,我们可以把Critic网络看成一个执行TD算法的网络,其更新公式可以表示为:
    ϕ ← ϕ − α ϕ ⋅ ∇ ϕ ( r t + γ V ( s t + 1 ; ϕ ) − V ( s t ; ϕ ) ) 2 \phi ←\phi -α_\phi \cdot \nabla_\phi(r_t+γV(s_{t+1};\phi)-V(s_t;\phi))^2 ϕϕαϕϕ(rt+γV(st+1;ϕ)V(st;ϕ))2

  2. Actor的更新(策略梯度)
    Actor利用Critic提供的优势函数,通过梯度上升优化策略:
    θ ← θ + A ( s t , a t ) ⋅ ∇ θ log ⁡ π ( a t ∣ s t ; θ ) \theta ← \theta+A(s_t,a_t)\cdot\nabla_\theta\log\pi(a_t|s_t;\theta) θθ+A(st,at)θlogπ(atst;θ)其中,优势函数 A ( s t , a t ) A(s_t,a_t) A(st,at)可以是TD形式,也可以是Q值形式。即 A ( s t , a t ) = r t + γ V ( s t + 1 ) − V ( s t ) A(s_t,a_t)=r_t+γV(s_{t+1})-V(s_t) A(st,at)=rt+γV(st+1)V(st) A ( s t , a t ) = Q ( s t , a t ) − V ( s t ) A(s_t,a_t)=Q(s_t,a_t)-V(s_t) A(st,at)=Q(st,at)V(st),前者为AC算法,后者为A2C算法。

2.AC算法代码实现

import gym
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from collections import deque
import random

# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = [
    'SimHei',  # 中易黑体 (Windows)
    'Microsoft YaHei',  # 微软雅黑 (Windows)
    'WenQuanYi Zen Hei',  # 文泉驿正黑 (Linux)
    'Arial Unicode MS'  # macOS
]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 超参数设置
GAMMA = 0.99  # 折扣因子
LR_ACTOR = 0.001  # Actor网络学习率
LR_CRITIC = 0.01  # Critic网络学习率
HIDDEN_SIZE = 128  # 网络隐藏层大小
reward_list = []

# 定义设备(自动检测GPU可用性)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


# 定义策略网络结构(Actor)
class Actor(nn.Module):
    def __init__(self, state_dim, action_dim):
        super(Actor, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(state_dim, HIDDEN_SIZE),
            nn.ReLU(),
            nn.Linear(HIDDEN_SIZE, action_dim),
            nn.Softmax(dim=-1)  # 输出动作概率
        )

    def forward(self, x):
        return self.fc(x)


# 定义价值网络结构(Critic)
class Critic(nn.Module):
    def __init__(self, state_dim):
        super(Critic, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(state_dim, HIDDEN_SIZE),
            nn.ReLU(),
            nn.Linear(HIDDEN_SIZE, 1)  # 输出状态价值
        )

    def forward(self, x):
        return self.fc(x)


# Actor-Critic智能体
class ACAgent:
    def __init__(self, state_dim, action_dim):
        self.action_dim = action_dim

        # 创建Actor和Critic网络
        self.actor = Actor(state_dim, action_dim).to(device)
        self.critic = Critic(state_dim).to(device)

        # 优化器
        self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=LR_ACTOR)
        self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=LR_CRITIC)

        # 存储回合数据的缓冲区
        self.states = []
        self.actions = []
        self.rewards = []
        self.next_states = []
        self.dones = []

    def choose_action(self, state):
        """ 根据策略网络采样动作 """
        state_tensor = torch.FloatTensor(state).to(device)
        probs = self.actor(state_tensor)
        action_dist = torch.distributions.Categorical(probs)
        action = action_dist.sample().item()
        return action

    def store_transition(self, state, action, reward, next_state, done):
        """ 存储转移数据(需要记录下一状态和终止标志) """
        self.states.append(state)
        self.actions.append(action)
        self.rewards.append(reward)
        self.next_states.append(next_state)
        self.dones.append(done)

    def update_model(self):
        """ 使用完整回合数据更新网络 """
        # 转换为张量
        states = torch.FloatTensor(np.array(self.states)).to(device)
        actions = torch.LongTensor(self.actions).to(device)
        rewards = torch.FloatTensor(self.rewards).to(device)
        next_states = torch.FloatTensor(np.array(self.next_states)).to(device)
        dones = torch.BoolTensor(self.dones).to(device)

        # ----------------- Critic更新 -----------------
        # 计算当前状态价值 V(s)
        current_v = self.critic(states).squeeze()

        # 计算目标价值 V_target = r + γ * V(s')
        with torch.no_grad():
            next_v = self.critic(next_states).squeeze()
            next_v[dones] = 0.0  # 终止状态无后续价值
            v_target = rewards + GAMMA * next_v

        # 计算Critic损失(均方误差)
        critic_loss = nn.MSELoss()(current_v, v_target)

        # 梯度下降
        self.critic_optimizer.zero_grad()
        critic_loss.backward()
        self.critic_optimizer.step()

        # ----------------- Actor更新 -----------------
        # 重新计算当前状态价值 V(s)(使用更新后的Critic)
        with torch.no_grad():
            current_v = self.critic(states).squeeze()
            next_v = self.critic(next_states).squeeze()
            next_v[dones] = 0.0
            td_errors = rewards + GAMMA * next_v - current_v

        # 计算策略梯度
        probs = self.actor(states)
        log_probs = torch.log(probs.gather(1, actions.unsqueeze(1)))
        actor_loss = -(log_probs.squeeze() * td_errors).mean()

        # 梯度上升
        self.actor_optimizer.zero_grad()
        actor_loss.backward()
        self.actor_optimizer.step()

        # 清空回合数据
        self.states = []
        self.actions = []
        self.rewards = []
        self.next_states = []
        self.dones = []


# 训练流程
def train_ac(env_name, episodes):
    env = gym.make(env_name)
    state_dim = env.observation_space.shape[0]
    action_dim = env.action_space.n

    agent = ACAgent(state_dim, action_dim)

    for episode in range(episodes):
        state = env.reset()[0]
        episode_reward = 0
        done = False

        while not done:
            # 1. 选择并执行动作
            action = agent.choose_action(state)
            next_state, reward, terminated, truncated, _ = env.step(action)
            done = terminated or truncated

            # 2. 存储转移数据
            agent.store_transition(state, action, reward, next_state, done)

            state = next_state
            episode_reward += reward

        # 3. 使用完整回合数据更新网络
        agent.update_model()

        # 记录训练进度
        reward_list.append(episode_reward)
        if (episode + 1) % 10 == 0:
            print(f"Episode: {episode + 1}, Reward: {episode_reward}")

    env.close()


if __name__ == "__main__":
    env_name = "CartPole-v1"
    episodes = 2000
    train_ac(env_name, episodes)
    np.save(f"result/AC2_rewards.npy", np.array(reward_list))
    plt.plot(range(episodes), reward_list)
    plt.xlabel('迭代次数')
    plt.ylabel('每代的总奖励值')
    plt.title('Actor-Critic的训练过程')
    plt.grid(True)
    plt.show()

绘图代码:

import numpy as np
import matplotlib.pyplot as plt

# 加载数据(注意路径与图中一致)
dqn_rewards = np.load("dqn_rewards.npy")
REFINORCE_rewards = np.load("REINFORCE_rewards.npy")
AC_rewards = np.load("AC2_rewards.npy")

plt.figure(figsize=(12, 6))

# 绘制原始曲线
plt.plot(dqn_rewards, alpha=0.3, color='blue', label='DQN (原始)')
plt.plot(REFINORCE_rewards, alpha=0.3, color='cyan', label='REINFORCE (原始)')
plt.plot(AC_rewards, alpha=0.3, color='cyan', label='AC (原始)')

# 绘制滚动平均曲线(窗口大小=50)
window_size = 50
plt.plot(np.convolve(dqn_rewards, np.ones(window_size)/window_size, mode='valid'),
         linewidth=2, color='navy', label='DQN (50轮平均)')
plt.plot(np.convolve(REFINORCE_rewards, np.ones(window_size)/window_size, mode='valid'),
         linewidth=2, color='bisque', label='REINFORCE (50轮平均)')
plt.plot(np.convolve(AC_rewards, np.ones(window_size)/window_size, mode='valid'),
         linewidth=2, color='magenta', label='AC (50轮平均)')

# 图表标注
plt.xlabel('训练轮次 (Episodes)', fontsize=12, fontfamily='SimHei')
plt.ylabel('奖励值', fontsize=12, fontfamily='SimHei')
plt.title('训练对比 (CartPole-v1)', fontsize=14, fontfamily='SimHei')
plt.legend(loc='upper left', prop={'family': 'SimHei'})
plt.grid(True, alpha=0.3)

# 保存图片(解决原图未保存的问题)
# plt.savefig('comparison.png', dpi=300, bbox_inches='tight')
plt.show()

结果对比图:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2337533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式(结构型)-桥接模式

目录 摘要 定义 类图 角色 具体实现 优缺点 优点 缺点 使用场景 使用案例 JDBC 和桥接模式 总结 摘要 在软件开发领域,随着系统规模和复杂性的不断攀升,如何设计出具有良好扩展性、灵活性以及可维护性的软件架构成为关键挑战。桥接模式作为一…

【MySQL】MySQL数据库 —— 简单认识

目录 1. 数据库的介绍 1.1 什么是数据库 1.2 数据库和数据结构之间关系 2. 数据库分类 2.1 关系型数据库(RDBMS) 2.2 非关系型数据库 2.3 区别 一些行内名词简单解释: 3. 关于mysql 主要学什么 4. MySQL中重要的概念 4.1 概念 4…

RNN - 语言模型

语言模型 给定文本序列 x 1 , … , x T x_1, \ldots, x_T x1​,…,xT​,语言模型的目标是估计联合概率 p ( x 1 , … , x T ) p(x_1, \ldots, x_T) p(x1​,…,xT​)它的应用包括 做预训练模型(eg BERT,GPT-3)生成本文&#xff…

过拟合、归一化、正则化、鞍点

过拟合 过拟合的本质原因往往是因为模型具备方差很大的权重参数。 定义一个有4个特征的输入,特征向量为,定义一个模型,其只有4个参数,表示为。当模型过拟合时,这四个权重参数的方差会很大,可以假设为。当经过这个模型后…

【python画图】:从入门到精通绘制完美柱状图

目录 Python数据可视化:从入门到精通绘制完美柱状图一、基础篇:快速绘制柱状图1.1 使用Matplotlib基础绘制1.2 使用Pandas快速绘图 二、进阶篇:专业级柱状图定制2.1 多系列柱状图2.2 堆叠柱状图2.3 水平柱状图 三、专业参数速查表Matplotlib …

基础知识:离线安装docker、docker compose

(1)离线安装docker 确认版本:Ubuntu 18.04 LTS - bionic 确认架构:X86_64 lsb_release -a uname -a 官方指南:https://docs.docker.com/engine/install/ 选择Ubuntu,发现页面上最低是Ubuntu20.04, 不要紧

畅游Diffusion数字人(27):解读字节跳动提出主题定制视频生成技术Phantom

畅游Diffusion数字人(0):专栏文章导航 前言:主题定制视频生成,特别是zero-shot主题定制视频生成,一直是当前领域的一个难点,之前的方法效果很差。字节跳动提出了一个技术主题定制视频生成技术Phantom,效果相比于之前的技术进步非常显著。这篇博客详细解读一下这一工作。 …

《Adaptive Layer-skipping in Pre-trained LLMs》- 论文笔记

作者:Xuan Luo, Weizhi Wang, Xifeng Yan Department of Computer Science, UC Santa Barbara xuan_luoucsb.edu, weizhiwangucsb.edu, xyancs.ucsb.edu 1. 引言与动机 1.1 背景 LLM 的成功与挑战: 大型语言模型 (LLMs) 在翻译、代码生成、推理等任务上取得巨大成…

微信小程序实现table样式,自带合并行合并列

微信小程序在代码编写过程好像不支持原生table的使用&#xff0c;在开发过程中偶尔又得需要拿table来展示。 1.table效果展示 1.wxml <view class"table-container"><view class"table"><view class"table-row"><view cla…

电脑的品牌和配置

我的笔记本是2020年买的&#xff0c;之前的订单找不到了&#xff0c;就知道是联想&#xff0c;不清楚具体的配置。 本文来源&#xff1a;腾讯元宝 检查系统信息&#xff08;Windows&#xff09; 这通常是 ​​联想&#xff08;Lenovo&#xff09;​​ 的型号代码。 81XV 是联想…

Redis面试——常用命令

一、String &#xff08;1&#xff09;设置值相关命令 1.1.1 SET 功能&#xff1a;设置一个键值对&#xff0c;如果键已存在则覆盖旧值语法&#xff1a; SET key value [EX seconds] [PX milliseconds] [NX|XX]EX seconds&#xff1a;设置键的过期时间为 seconds 秒 PX milli…

Swin-Transformer-UNet改进:融合Global-Local Spatial Attention (GLSA) 模块详解

目录 1.模块概述 2.swinUNet网络 3. 完整代码 1.模块概述 Global-Local Spatial Attention (GLSA) 是一种先进的注意力机制模块,专为计算机视觉任务设计,能够同时捕捉全局上下文信息和局部细节特征。 该模块通过创新的双分支结构和自适应融合机制,显著提升了特征表示能…

ubuntu 向右拖动窗口后消失了、找不到了

这是目前单显示器的设置&#xff0c;因为实际只有1个显示器&#xff0c;之前的设置如下图所示&#xff0c;有2个显示器&#xff0c;一个主显示器&#xff0c;一个23寸的显示器 ubuntu 22.04 系统 今天在操作窗口时&#xff0c;向右一滑&#xff0c;发现这个窗口再也不显示了、找…

2025最新版微软GraphRAG 2.0.0本地部署教程:基于Ollama快速构建知识图谱

一、前言 微软近期发布了知识图谱工具 GraphRAG 2.0.0&#xff0c;支持基于本地大模型&#xff08;Ollama&#xff09;快速构建知识图谱&#xff0c;显著提升了RAG&#xff08;检索增强生成&#xff09;的效果。本文手把手教你如何从零部署&#xff0c;并附踩坑记录和性能实测…

libevent服务器附带qt界面开发(附带源码)

本章是入门章节&#xff0c;讲解如何实现一个附带界面的服务器&#xff0c;后续会完善与优化 使用qt编译libevent源码演示视频qt的一些知识 1.主要功能有登录界面 2.基于libevent实现的服务器的业务功能 使用qt编译libevent 下载这个&#xff0c;其他版本也可以 主要是github上…

智能体数据分析

数据概览&#xff1a; 展示智能体的累计对话次数、累计对话用户数、对话满意度、累计曝光次数。数据分析&#xff1a; 统计对话分析、流量分析、用户分析、行为分析数据指标&#xff0c;帮助开发者完成精准的全面分析。 ps&#xff1a;数据T1更新&#xff0c;当日12点更新前一天…

STM32(M4)入门: 概述、keil5安装与模板建立(价值 3w + 的嵌入式开发指南)

前言&#xff1a;本教程内容源自信盈达教培资料&#xff0c;价值3w&#xff0c;使用的是信盈达的405开发版&#xff0c;涵盖面很广&#xff0c;流程清晰&#xff0c;学完保证能从新手入门到小高手&#xff0c;软件方面可以无基础学习&#xff0c;硬件学习支持两种模式&#xff…

采用若依vue 快速开发系统功能模块

文章目录 运行若依项目 科室管理科室查询-后端代码实现科室查询-前端代码实现科室名称状态搜索科室删除-后端代码实现科室删除-前端代码实现科室新增-后端代码实现科室新增-前端代码实现科室修改-后端代码实现前端代码实现角色权限实现 运行若依项目 运行redis 创建数据库 修改…

HTML:表格数据展示区

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>人员信息表</title><link rel"styl…

Oracle测试题目及笔记(单选)

所有题目来自于互联网搜索 当 Oracle 服务器启动时&#xff0c;下列哪种文件不是必须的&#xff08;D&#xff09;。 A&#xff0e;数据文件 B&#xff0e;控制文件 C&#xff0e;日志文件 D&#xff0e;归档日志文件 数据文件、日志文件-在数据库的打开阶段使用 控制文件-在数…