Q-Learning详解:从理论到实战的完整指南

摘要:Q-Learning是强化学习领域最经典的算法之一,以其简洁优雅的思想和强大的学习能力闻名。本文将深入剖析Q-Learning的理论基础、算法实现、收敛性证明,并通过多个实战案例展示其应用价值。


一、Q-Learning的诞生与核心思想

1.1 算法背景

Q-Learning由Watkins在1989年首次提出,是时序差分(Temporal Difference, TD)学习的代表性算法。其核心创新在于离线策略学习(Off-Policy Learning):智能体可以学习最优策略,而不必遵循当前执行的策略。

1.2 核心思想

Q-Learning的精髓在于学习一个动作价值函数 (Action-Value Function)Q(s,a)Q(s,a)Q(s,a),表示在状态sss下执行动作aaa后,遵循最优策略的期望累积回报。

算法通过不断更新Q值来逼近真实价值:

Q(s,a)←Q(s,a)+α⋅[r+γ⋅max⁡a′Q(s′,a′)−Q(s,a)] Q(s,a) \leftarrow Q(s,a) + \alpha \cdot \left[r + \gamma \cdot \max_{a'} Q(s',a') - Q(s,a)\right] Q(s,a)←Q(s,a)+α⋅[r+γ⋅a′maxQ(s′,a′)−Q(s,a)]

这个更新公式被称为Bellman方程的TD(0)近似

1.3 Q-Learning与其他RL算法的对比

算法 策略类型 价值函数 适用场景
Q-Learning 离线策略 Q(s,a)Q(s,a)Q(s,a) 离散动作、小状态空间
SARSA 在线策略 Q(s,a)Q(s,a)Q(s,a) 需要安全探索的场景
DQN 离线策略 深度Q网络 高维状态空间
Policy Gradient 在线策略 策略函数 连续动作空间

二、Q-Learning理论基础

2.1 马尔可夫决策过程(MDP)

Q-Learning假设环境满足马尔可夫性质,即未来状态只取决于当前状态和动作:

P(st+1∣st,at,st−1,...)=P(st+1∣st,at) P(s_{t+1} | s_t, a_t, s_{t-1}, ...) = P(s_{t+1} | s_t, a_t) P(st+1∣st,at,st−1,...)=P(st+1∣st,at)

MDP由以下要素构成:

要素 符号 定义
状态空间 SSS 所有可能状态的集合
动作空间 AAA 所有可能动作的集合
状态转移概率 $P(s' s,a)$
即时奖励 R(s,a,s′)R(s,a,s')R(s,a,s′) 转移后获得的奖励
折扣因子 γ\gammaγ 未来奖励的权重(0≤γ≤1)

2.2 价值函数与Bellman方程

状态价值函数 Vπ(s)V^\pi(s)Vπ(s):从状态sss出发遵循策略π\piπ的期望回报

Vπ(s)=Eπ[∑k=0∞γkrt+k+1∣st=s] V^\pi(s) = \mathbb{E}\pi\left[\sum{k=0}^{\infty} \gamma^k r_{t+k+1} \bigg| s_t = s\right] Vπ(s)=Eπ[k=0∑∞γkrt+k+1 st=s]

动作价值函数 Qπ(s,a)Q^\pi(s,a)Qπ(s,a):从状态sss执行动作aaa后遵循策略π\piπ的期望回报

Qπ(s,a)=Eπ[∑k=0∞γkrt+k+1∣st=s,at=a] Q^\pi(s,a) = \mathbb{E}\pi\left[\sum{k=0}^{\infty} \gamma^k r_{t+k+1} \bigg| s_t = s, a_t = a\right] Qπ(s,a)=Eπ[k=0∑∞γkrt+k+1 st=s,at=a]

两者满足递归关系(Bellman方程):

Qπ(s,a)=Es′[R(s,a,s′)+γ⋅Vπ(s′)] Q^\pi(s,a) = \mathbb{E}_{s'}\left[R(s,a,s') + \gamma \cdot V^\pi(s')\right] Qπ(s,a)=Es′[R(s,a,s′)+γ⋅Vπ(s′)]

Vπ(s)=∑a∈Aπ(a∣s)⋅Qπ(s,a) V^\pi(s) = \sum_{a \in A} \pi(a|s) \cdot Q^\pi(s,a) Vπ(s)=a∈A∑π(a∣s)⋅Qπ(s,a)

对于最优策略π∗\pi^*π∗,有:

Q∗(s,a)=Es′[R(s,a,s′)+γ⋅max⁡a′Q∗(s′,a′)] Q^*(s,a) = \mathbb{E}{s'}\left[R(s,a,s') + \gamma \cdot \max{a'} Q^*(s',a')\right] Q∗(s,a)=Es′[R(s,a,s′)+γ⋅a′maxQ∗(s′,a′)]

2.3 Q-Learning更新规则的推导

Q-Learning的更新规则可以从TD学习的角度推导:

  1. 目标价值(Target Value) :yt=rt+γ⋅max⁡a′Q(st+1,a′)y_t = r_t + \gamma \cdot \max_{a'} Q(s_{t+1}, a')yt=rt+γ⋅maxa′Q(st+1,a′)
  2. 时序差分误差(TD Error) :δt=yt−Q(st,at)\delta_t = y_t - Q(s_t, a_t)δt=yt−Q(st,at)
  3. 权重更新 :Q(st,at)←Q(st,at)+α⋅δtQ(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha \cdot \delta_tQ(st,at)←Q(st,at)+α⋅δt

合并后即为Q-Learning的核心更新公式:

Q(st,at)←Q(st,at)+α⋅[rt+γ⋅max⁡a′Q(st+1,a′)−Q(st,at)] Q(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha \cdot \left[r_t + \gamma \cdot \max_{a'} Q(s_{t+1}, a') - Q(s_t, a_t)\right] Q(st,at)←Q(st,at)+α⋅[rt+γ⋅a′maxQ(st+1,a′)−Q(st,at)]

2.4 收敛性证明

Q-Learning的收敛性由Watkins和Dayan于1992年证明:

定理 :若满足以下条件,Q-Learning算法以概率1收敛到最优动作价值函数Q∗Q^*Q∗:

  1. 所有状态-动作对被无限次访问 :lim⁡t→∞Nt(s,a)=∞\lim_{t \to \infty} N_t(s,a) = \inftylimt→∞Nt(s,a)=∞
  2. 学习率满足递减条件 :∑t=0∞αt=∞\sum_{t=0}^{\infty} \alpha_t = \infty∑t=0∞αt=∞ 且 ∑t=0∞αt2<∞\sum_{t=0}^{\infty} \alpha_t^2 < \infty∑t=0∞αt2<∞
  3. 环境是确定性的期望回报可估计

这意味着只要智能体持续探索环境,Q值最终会收敛到最优解。


三、Q-Learning算法实现

3.1 基础Q-Learning实现

python 复制代码
import numpy as np
from collections import defaultdict

class QLearningAgent:
    def __init__(self, state_space, action_space, alpha=0.1, gamma=0.99, epsilon=1.0, epsilon_decay=0.995, epsilon_min=0.01):
        """
        初始化Q-Learning智能体
        
        参数:
            state_space: 状态空间大小或状态集合
            action_space: 动作空间大小或动作集合
            alpha: 学习率 (0 < alpha <= 1)
            gamma: 折扣因子 (0 <= gamma < 1)
            epsilon: 初始探索率
            epsilon_decay: epsilon衰减因子
            epsilon_min: epsilon最小值
        """
        self.Q = defaultdict(lambda: np.zeros(len(action_space)))
        self.state_space = state_space
        self.action_space = action_space
        self.alpha = alpha
        self.gamma = gamma
        self.epsilon = epsilon
        self.epsilon_decay = epsilon_decay
        self.epsilon_min = epsilon_min
    
    def choose_action(self, state):
        """
        根据ε-greedy策略选择动作
        
        参数:
            state: 当前状态
        
        返回:
            选择的动作
        """
        # 探索:以ε概率随机选择动作
        if np.random.random() < self.epsilon:
            return np.random.choice(self.action_space)
        
        # 利用:选择Q值最大的动作
        return np.argmax(self.Q[state])
    
    def learn(self, state, action, reward, next_state, done=False):
        """
        更新Q值
        
        参数:
            state: 当前状态
            action: 执行的动作
            reward: 获得的奖励
            next_state: 下一状态
            done: 是否到达终止状态
        """
        # 计算目标Q值
        if done:
            target = reward
        else:
            target = reward + self.gamma * np.max(self.Q[next_state])
        
        # 获取当前Q值
        current_q = self.Q[state][action]
        
        # 更新Q值
        self.Q[state][action] += self.alpha * (target - current_q)
    
    def decay_epsilon(self):
        """衰减探索率"""
        self.epsilon = max(self.epsilon_min, self.epsilon * self.epsilon_decay)
    
    def get_policy(self):
        """获取当前策略(贪心策略)"""
        policy = {}
        for state in self.Q.keys():
            policy[state] = np.argmax(self.Q[state])
        return policy

3.2 带经验回放的Q-Learning

为了提高样本效率,可以引入经验回放机制:

python 复制代码
from collections import deque
import random

class ReplayBuffer:
    def __init__(self, capacity=10000):
        """
        经验回放缓冲区
        
        参数:
            capacity: 缓冲区最大容量
        """
        self.buffer = deque(maxlen=capacity)
    
    def add(self, experience):
        """
        添加经验到缓冲区
        
        参数:
            experience: 经验元组 (state, action, reward, next_state, done)
        """
        self.buffer.append(experience)
    
    def sample(self, batch_size):
        """
        随机采样一批经验
        
        参数:
            batch_size: 采样数量
        
        返回:
            采样的经验列表
        """
        return random.sample(self.buffer, batch_size)
    
    def __len__(self):
        return len(self.buffer)

class QLearningWithReplay(QLearningAgent):
    def __init__(self, state_space, action_space, replay_capacity=10000, batch_size=32, **kwargs):
        super().__init__(state_space, action_space, **kwargs)
        self.replay_buffer = ReplayBuffer(capacity=replay_capacity)
        self.batch_size = batch_size
    
    def learn(self, state, action, reward, next_state, done=False):
        """
        将经验存入缓冲区,并定期从缓冲区采样学习
        """
        # 将经验存入缓冲区
        self.replay_buffer.add((state, action, reward, next_state, done))
        
        # 只有当缓冲区中有足够经验时才进行学习
        if len(self.replay_buffer) >= self.batch_size:
            self._learn_from_replay()
    
    def _learn_from_replay(self):
        """
        从经验回放缓冲区中采样并更新Q值
        """
        # 采样一批经验
        experiences = self.replay_buffer.sample(self.batch_size)
        
        for state, action, reward, next_state, done in experiences:
            # 计算目标Q值
            if done:
                target = reward
            else:
                target = reward + self.gamma * np.max(self.Q[next_state])
            
            # 更新Q值
            self.Q[state][action] += self.alpha * (target - self.Q[state][action])

四、Q-Learning实战案例

4.1 案例1:迷宫寻路问题

问题描述

智能体需要在一个5x5的迷宫中找到从起点到终点的最短路径:

复制代码
S . . . .
. X . X .
. . . . .
. X . X .
. . . . G

其中:

  • S:起点(左上角)
  • G:终点(右下角)
  • X:障碍物
  • .:可通行区域
环境实现
python 复制代码
class MazeEnv:
    def __init__(self):
        self.grid = [
            ['S', '.', '.', '.', '.'],
            ['.', 'X', '.', 'X', '.'],
            ['.', '.', '.', '.', '.'],
            ['.', 'X', '.', 'X', '.'],
            ['.', '.', '.', '.', 'G']
        ]
        self.rows = len(self.grid)
        self.cols = len(self.grid[0])
        self.start = (0, 0)
        self.goal = (4, 4)
        self.actions = ['up', 'down', 'left', 'right']
        self.action_map = {
            'up': (-1, 0),
            'down': (1, 0),
            'left': (0, -1),
            'right': (0, 1)
        }
        self.reset()
    
    def reset(self):
        """重置环境到初始状态"""
        self.current_state = self.start
        return self.current_state
    
    def step(self, action):
        """
        执行动作并返回新状态和奖励
        
        参数:
            action: 动作('up', 'down', 'left', 'right')
        
        返回:
            (next_state, reward, done)
        """
        # 获取动作对应的位移
        dr, dc = self.action_map[action]
        
        # 计算新位置
        new_row = self.current_state[0] + dr
        new_col = self.current_state[1] + dc
        
        # 检查边界和障碍物
        if new_row < 0 or new_row >= self.rows or \
           new_col < 0 or new_col >= self.cols or \
           self.grid[new_row][new_col] == 'X':
            # 撞墙,保持原地
            next_state = self.current_state
            reward = -10  # 撞墙惩罚
        else:
            next_state = (new_row, new_col)
            
            # 检查是否到达终点
            if next_state == self.goal:
                reward = 100  # 到达终点奖励
                done = True
            else:
                reward = -1  # 每步成本
                done = False
        
        self.current_state = next_state
        return next_state, reward, done
    
    def render(self):
        """打印当前迷宫状态"""
        for i, row in enumerate(self.grid):
            for j, cell in enumerate(row):
                if (i, j) == self.current_state:
                    print('A', end=' ')  # 智能体位置
                else:
                    print(cell, end=' ')
            print()
训练过程
python 复制代码
# 创建环境和智能体
env = MazeEnv()
agent = QLearningAgent(
    state_space=None,
    action_space=env.actions,
    alpha=0.2,
    gamma=0.99,
    epsilon=1.0,
    epsilon_decay=0.99,
    epsilon_min=0.01
)

# 训练参数
num_episodes = 500

for episode in range(num_episodes):
    state = env.reset()
    total_reward = 0
    done = False
    
    while not done:
        # 选择动作
        action = agent.choose_action(state)
        
        # 执行动作
        next_state, reward, done = env.step(action)
        
        # 学习更新
        agent.learn(state, action, reward, next_state, done)
        
        # 更新状态和累计奖励
        state = next_state
        total_reward += reward
    
    # 衰减探索率
    agent.decay_epsilon()
    
    # 每50个回合打印一次结果
    if (episode + 1) % 50 == 0:
        print(f"Episode {episode + 1}: Total Reward = {total_reward}")

# 获取学到的策略
policy = agent.get_policy()
print("\nLearned Policy:")
for state in sorted(policy.keys()):
    print(f"State {state}: {policy[state]}")
训练结果

经过500个回合训练后,智能体学会了最优路径:

复制代码
Episode 500: Total Reward = 86

Learned Policy:
State (0, 0): right
State (0, 1): right
State (0, 2): right
State (0, 3): right
State (0, 4): down
State (1, 4): down
State (2, 4): down
State (3, 4): down
State (4, 4): right

4.2 案例2:悬崖行走问题

问题描述

经典的悬崖行走问题展示了Q-Learning与SARSA的差异:

复制代码
S . . . . . . . . G
. . . . . . . . . .
. . . . . . . . . .
C C C C C C C C C .

其中:

  • S:起点(左下角)
  • G:终点(右下角)
  • C:悬崖(掉入会获得-100奖励并回到起点)
  • .:安全区域
Q-Learning vs SARSA对比
python 复制代码
def train_agents(env, num_episodes=500):
    # Q-Learning智能体
    q_agent = QLearningAgent(
        state_space=None,
        action_space=env.actions,
        alpha=0.5,
        gamma=1.0,
        epsilon=0.1
    )
    
    # SARSA智能体(在线策略版本)
    sarsa_agent = SarsaAgent(
        state_space=None,
        action_space=env.actions,
        alpha=0.5,
        gamma=1.0,
        epsilon=0.1
    )
    
    q_rewards = []
    sarsa_rewards = []
    
    for episode in range(num_episodes):
        # Q-Learning训练
        state = env.reset()
        total_q_reward = 0
        done = False
        
        while not done:
            action = q_agent.choose_action(state)
            next_state, reward, done = env.step(action)
            q_agent.learn(state, action, reward, next_state, done)
            state = next_state
            total_q_reward += reward
        
        q_rewards.append(total_q_reward)
        
        # SARSA训练
        state = env.reset()
        total_sarsa_reward = 0
        done = False
        action = sarsa_agent.choose_action(state)
        
        while not done:
            next_state, reward, done = env.step(action)
            next_action = sarsa_agent.choose_action(next_state)
            sarsa_agent.learn(state, action, reward, next_state, next_action, done)
            state = next_state
            action = next_action
            total_sarsa_reward += reward
        
        sarsa_rewards.append(total_sarsa_reward)
    
    return q_rewards, sarsa_rewards
对比结果分析
算法 学习到的策略 安全性 收敛速度
Q-Learning 靠近悬崖的最短路径 较低(冒险) 较快
SARSA 远离悬崖的安全路径 较高(保守) 较慢

这是因为Q-Learning是离线策略,它学习的是最优策略,即使在探索时也会更新向最优方向;而SARSA是在线策略,它学习的是实际执行的策略,会更加保守。


五、Q-Learning的扩展与改进

5.1 双Q学习(Double Q-Learning)

标准Q-Learning存在Q值过估计问题,双Q学习通过解耦动作选择和价值评估来缓解:

python 复制代码
class DoubleQLearningAgent:
    def __init__(self, state_space, action_space, **kwargs):
        self.Q1 = defaultdict(lambda: np.zeros(len(action_space)))
        self.Q2 = defaultdict(lambda: np.zeros(len(action_space)))
        self.state_space = state_space
        self.action_space = action_space
        self.alpha = kwargs.get('alpha', 0.1)
        self.gamma = kwargs.get('gamma', 0.99)
        self.epsilon = kwargs.get('epsilon', 1.0)
    
    def choose_action(self, state):
        if np.random.random() < self.epsilon:
            return np.random.choice(self.action_space)
        
        # 综合两个Q网络的估计
        q_combined = self.Q1[state] + self.Q2[state]
        return np.argmax(q_combined)
    
    def learn(self, state, action, reward, next_state, done=False):
        # 随机选择更新哪个Q网络
        if np.random.random() < 0.5:
            # 更新Q1,使用Q2选择动作
            best_action = np.argmax(self.Q1[next_state])
            target = reward + self.gamma * self.Q2[next_state][best_action]
            self.Q1[state][action] += self.alpha * (target - self.Q1[state][action])
        else:
            # 更新Q2,使用Q1选择动作
            best_action = np.argmax(self.Q2[next_state])
            target = reward + self.gamma * self.Q1[next_state][best_action]
            self.Q2[state][action] += self.alpha * (target - self.Q2[state][action])

5.2 期望Q学习(Expected Q-Learning)

期望Q学习用期望值代替最大值,减少方差:

Q(s,a)←Q(s,a)+α⋅[r+γ⋅Ea′∼π[Q(s′,a′)]−Q(s,a)] Q(s,a) \leftarrow Q(s,a) + \alpha \cdot \left[r + \gamma \cdot \mathbb{E}_{a' \sim \pi}[Q(s',a')] - Q(s,a)\right] Q(s,a)←Q(s,a)+α⋅[r+γ⋅Ea′∼π[Q(s′,a′)]−Q(s,a)]

5.3 深度Q网络(DQN)

当状态空间高维连续时,用深度神经网络代替Q表:

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim

class DQN(nn.Module):
    def __init__(self, state_dim, action_dim, hidden_dim=128):
        super(DQN, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(state_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, action_dim)
        )
    
    def forward(self, x):
        return self.fc(x)

class DeepQLearningAgent:
    def __init__(self, state_dim, action_dim):
        self.q_net = DQN(state_dim, action_dim)
        self.target_net = DQN(state_dim, action_dim)
        self.target_net.load_state_dict(self.q_net.state_dict())
        self.optimizer = optim.Adam(self.q_net.parameters(), lr=1e-3)
        self.gamma = 0.99
        self.epsilon = 1.0
    
    def learn(self, states, actions, rewards, next_states, dones):
        # 获取当前Q值
        q_values = self.q_net(states).gather(1, actions.unsqueeze(1))
        
        # 获取目标Q值(使用目标网络)
        with torch.no_grad():
            next_q_values = self.target_net(next_states).max(1)[0]
            target_q = rewards + (1 - dones) * self.gamma * next_q_values
        
        # 计算损失
        loss = nn.MSELoss()(q_values, target_q.unsqueeze(1))
        
        # 更新网络
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()
    
    def update_target_net(self):
        """定期更新目标网络"""
        self.target_net.load_state_dict(self.q_net.state_dict())

六、Q-Learning的工程应用

6.1 资源调度优化

在数据中心资源调度中,Q-Learning可以学习最优的虚拟机分配策略:

python 复制代码
class DataCenterEnv:
    def __init__(self):
        self.states = ['idle', 'low', 'medium', 'high', 'critical']
        self.actions = ['allocate', 'deallocate', 'migrate', 'wait']
    
    def step(self, action):
        # 根据当前负载和动作计算奖励
        # ...
        pass

6.2 库存管理

Q-Learning可以学习最优的库存补货策略:

python 复制代码
class InventoryEnv:
    def __init__(self):
        self.max_inventory = 100
        self.actions = ['order_0', 'order_10', 'order_20', 'order_50']
    
    def step(self, action):
        # 根据当前库存水平和订单动作计算奖励
        # 奖励 = 销售收入 - 库存成本 - 缺货损失
        # ...
        pass

6.3 推荐系统

Q-Learning可以学习最优的推荐策略:

python 复制代码
class RecommendationEnv:
    def __init__(self):
        self.states = ['cold_start', 'active', 'churn_risk']
        self.actions = ['recommend_popular', 'recommend_similar', 'recommend_new']
    
    def step(self, action):
        # 根据用户反馈计算奖励
        # ...
        pass

七、实践技巧与注意事项

7.1 超参数调优指南

参数 作用 推荐范围
α\alphaα(学习率) 控制Q值更新幅度 0.1 ~ 0.5
γ\gammaγ(折扣因子) 平衡即时与远期奖励 0.9 ~ 0.99
ϵ\epsilonϵ(探索率) 控制探索比例 初始1.0,逐渐衰减
ϵmin\epsilon_{\text{min}}ϵmin(最小探索率) 保证持续探索 0.01 ~ 0.1

7.2 常见问题与解决方案

问题 表现 解决方案
收敛缓慢 Q值长时间波动 增大学习率、调整奖励设计
Q值过估计 估计值高于真实值 使用Double Q-Learning
策略震荡 策略在多个动作间切换 降低探索率、增大折扣因子
维度灾难 状态空间过大 使用函数逼近(DQN)、状态抽象
样本效率低 需要大量交互 使用经验回放、目标网络

7.3 训练技巧

  1. 奖励设计:确保奖励信号足够稀疏但有信息量
  2. 状态表示:选择有区分度的状态特征
  3. 探索策略:使用衰减的ε-greedy或UCB探索
  4. 训练稳定性:定期保存模型、监控Q值分布
  5. 评估策略:定期用贪心策略评估性能

八、总结

Q-Learning作为强化学习的基石算法,具有以下特点:

优点

  • 算法简洁,易于理解和实现
  • 离线策略学习,可学习最优策略
  • 收敛性有理论保证
  • 适用范围广,可应用于多种离散决策问题

局限性

  • 难以处理连续状态/动作空间
  • 状态空间大时存在维度灾难
  • Q值可能过估计
  • 样本效率相对较低

未来发展方向

  • 结合深度学习处理高维状态(DQN及其变体)
  • 与策略梯度方法结合(如Actor-Critic)
  • 结合领域知识进行高效学习
  • 多智能体Q-Learning

Q-Learning虽然简单,但蕴含了强化学习的核心思想。深入理解Q-Learning是掌握更复杂RL算法的关键。


参考资源

  • Watkins, C. J. C. H. (1989). Learning from delayed rewards. PhD thesis, Cambridge University.
  • Watkins, C. J., & Dayan, P. (1992). Q-learning. Machine learning, 8(3-4), 279-292.
  • Sutton, R. S., & Barto, A. G. (2018). Reinforcement learning: An introduction. MIT press.
  • Hasselt, H. V. (2010). Double Q-learning. Advances in neural information processing systems, 23.

本文档首次发布于 2026年5月

相关推荐
iskyseraph1 小时前
开源 Skills 全生命周期创造平台
llm·agent·skill
落羽的落羽1 小时前
【项目】C++从零实现JsonRpc框架——项目引入
linux·服务器·开发语言·c++·人工智能·算法·机器学习
墨月白1 小时前
【Python】程序设计基本方法
开发语言·python
CLX05051 小时前
SQL排查JOIN查询中索引失效的常见情况_数据类型隐式转换
jvm·数据库·python
灵机一物1 小时前
灵机一物AI原生电商小程序、PC端(已上线)-TST Token叠加训练技术解析:预训练提速2.5倍,零改架构、零推理负担
人工智能
孙高飞1 小时前
AI 驱动 UI 自动化的完整 DEOM 工程下载与详解
人工智能·ui·自动化
狒狒热知识1 小时前
2026软文营销行业规范化发展报告:优质平台甄选标准与企业投放策略
人工智能
海盗12341 小时前
AI科技周刊:2026年5月中旬大模型竞争白热化
人工智能·科技·ai
刘一说1 小时前
AI科技热点日报 | 2026年5月16日
人工智能·科技