当前位置: 首页 > news >正文

【深度强化学习】(2) Double DQN 模型解析,附Pytorch完整代码

大家好,今天和大家分享一个深度强化学习算法 DQN 的改进版 Double DQN,并基于 OpenAI 的 gym 环境库完成一个小游戏,完整代码可以从我的 GitHub 中获得:

https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Model


1. 算法原理

1.1 DQN 原理回顾

DQN 算法的原理是指导机器人不断与环境交互,理解最佳的行为方式,最终学习到最优的行为策略,机器人与环境的交互过程如下图所示。 

机器人与环境的交互过程是机器人在 t 时刻,采取动作 a_t 并作用于环境,然后环境从 t 时刻状态 s_t 转变到 t+1 时刻状态 s_{t+1},同时奖励函数对 a_t 进行评价得到奖励值 r_t。机器人根据 r_t 不断优化行为轨迹,最终学习到最优的行为策略。

整个强化学习过程可简化为马尔可夫决策过程(MDP)。其中所有状态均具备马尔可夫性。MDP 可用一个五元组 \left \langle S,A,P,R,\gamma \right \rangle 表示,各元素意义如下: 

(1)S 是有限状态集合,即机器人在环境中探索到的所有可能状态。s_t 表示机器人在 t 时刻的状态。

(2)A 是有限动作集合,即智能体根据 s_t 采取的所有可能动作集合。a_t 表示机器人在t 时刻状态采取的行为

(3)P 是状态转移概率,定义如下:P_{s_{t+1}}^a = P[S_{t+1}=s_{t+1}|S_t=s, A_t=a]

(4)R 是奖励函数,即机器人基于 s_t 采取 a_t 后获得的期望奖励,定义如下:R_s^a = E[R_{t+1}|s_{t+1}|S_t=s, A_t=a]

(5)γ 代表折扣因子,值域 [0,1],即未来的期望奖励在当前时刻的价值比例。

MDP 中,价值函数包括状态价值函数和动作价值函数。动作价值函数(Q 函数)表示在策略 \pi 的指导下,根据状态 s,采取行为 a 所获得的期望回报策略 \pi 表示状态到行为的映射,相当于机器人的决策策略,并根据不同的状态选择不同的行为,即 a = \pi (s)。机器人在策略 \pi 的指导下,Q 函数的定义如下:

Q_\pi (s,a)=E_\pi [G_t|S_t=s,A_t=a]

式中 G_t 表示折扣奖励,定义如下:

G_t=R_{t+1} + \gamma R_{t+2} + ... = \sum_{k=t}^{T}\gamma ^{k-t}R(s_k,a_k)

式中 \gamma ^t 随训练过程迭代减小,\gamma ^t 越小表示未来的奖励对当前时刻的奖励影响越小。

Q 函数的贝尔曼方程表示如下:

Q_\pi (s_t,a_t)=E[R(s_t,a_t)+\gamma E_{a_{t+1\sim \pi }}Q_\pi (s_{t+1}, a_{t+1})]

式中,R(s_t,a_t) 表示机器人在 s_t 时采取 a_t 所获得的即时奖励,等式右侧第二项表示机
器人执行策略 \pi 产生的未来累计奖励的期望

通过选取最大动作价值函数求解最优行为策略的公式表示如下: 

a = argmax_{a\in A}Q(s,a)

DQN 算法通过行为的奖励值构造算法训练的标签,并且其中的经验回放(Experience Replay)和目标网络有效的解决了数据相关性和非静态分布的问题。DQN 算法的结构示意图如下。

DQN 的网络结构由目标网络和估计网络组成,这两个网络的结构相同但参数不同估计网络具有最新的网络参数,计算当前状态-动作对的价值,并定期更新目标网络的参数,使其计算目标 Q 值。双网络结构打破了数据之间的相关性,使DQN 学习不同的数据分布。经验回放部分储存了智能体(机器人)的历史行为信息,其中包括多组行为序列对 (s,a,r,s'),即当前时刻状态 s ,行为 a ,奖励 r 以及下一时刻状态 s'。当 DQN 算法更新时,随机从经验池中抽取部分行为序列对进行经验回放,这种方式解决了经验池中数据相关性强和非静态分布导致的模型泛化能力差的问题。

DQN 算法通过贪婪法直接获得目标 Q 值贪婪法通过最大化方式使 Q 值快速向可能的优化目标收敛但易导致过估计Q 值的问题,使模型具有较大的偏差。DQN 算法过估计 Q 值的问题不适合机器人操作行为的研究,采用 Double DQN 算法解耦动作的选择和目标 Q 值的计算,以解决过估计 Q 值的问题。 


1.2 Double DQN 原理

Double  DQN 算法是 DQN 算法的改进版本,解决了 DQN 算法过估计行为价值的问题。DQN 算法中,某一时刻状态为非终止状态时,目标 Q 值的计算公式如下所示:

y_j = r_j + \gamma max_{a'}Q(s_{j+1},a';\theta ')

Double  DQN 算法不直接通过最大化的方式选取目标网络计算的所有可能 Q 值,而是首先通过估计网络选取最大 Q 值对应的动作,公式表示如下: 

a_{max} = argmax_a Q (s_{t+1}, a ; \theta )

然后目标网络根据 a_{max} 计算目标 Q 值,公式表示如下:

y_j = r_j+\gamma Q(s_{j+1},a_{max};\theta ')

最后将上面两个公式结合,目标 Q 值的最终表示形式如下:

y_j = r_j + \gamma Q(s_{j+1},argmax_aQ(s_{t+1,a;\theta });\theta ')

目标是最小化目标函数,即最小化估计 Q 值和目标 Q 值的差值,公式如下:

\delta = |Q(s_t,a_t)-y_t|=|Q(s_t,a_t;\theta ) - (r_t + \gamma Q(S_{t+1},argmax_aQ(s_{t+1},a;\theta );\theta ')) |

结合目标函数,损失函数定义如下:

loss=\begin{Bmatrix} \frac{1}{2}\delta ^2 & for |\delta | \leqslant 1 \\ |\delta |-\frac{1}{2} & otherwize \end{Bmatrix}

Double DQN 的伪代码:

Double DQN 算法结构如下。在 Double DQN 框架中存在两个神经网络模型,分别是训练网络与目标网络。这两个神经网络模型的结构完全相同,但是权重参数不同;每训练一段之间后,训练网络的权重参数才会复制给目标网络。训练时,训练网络用于估计当前的 Q(s_t,a),而目标网络用于估计 max_aQ(s_{t+1},a),这样就能保证真实值 Q_{target}(s_t,a) 的估计不会随着训练网络的不断自更新而变化过快。此外,DQN 还是一种支持离线学习的框架,即通过构建经验池的方式离线学习过去的经验。将均方误差 MSE(Q_{train}, Q_{target}) 作为训练模型的损失函数,通过梯度下降法进行反向传播,对训练模型进行更新;若干轮经验池采样后,再将训练模型的权重赋给目标模型,以此进行 Double DQN 框架下的模型自学习。 


2. 代码实现

模型构建部分的代码如下:

import torch
from torch import nn
from torch.nn import functional as F
import numpy as np
import collections  # 队列
import random# ----------------------------------- #
#(1)经验回放池
# ----------------------------------- #class ReplayBuffer:def __init__(self, capacity):# 创建一个队列,先进先出,队列长度不变self.buffer = collections.deque(maxlen=capacity)# 填充经验池def add(self, state, action, reward, next_state, done):self.buffer.append((state, action, reward, next_state, done))# 随机采样batch组样本数据def sample(self, batch_size):transitions = random.sample(self.buffer, batch_size)# 分别取出这些数据,*获取list中的所有值state, action, reward, next_state, done = zip(*transitions)# 将state变成数组,后面方便计算return np.array(state), action, reward, np.array(next_state), done# 队列的长度def size(self):return len(self.buffer)# ----------------------------------- #
#(2)构造网络,训练网络和目标网络共用该结构
# ----------------------------------- #class Net(nn.Module):def __init__(self, n_states, n_hiddens, n_actions):super(Net, self).__init__()# 只有一个隐含层self.fc1 = nn.Linear(n_states, n_hiddens)self.fc2 = nn.Linear(n_hiddens, n_actions)# 前向传播def forward(self, x):x = self.fc1(x)  # [b,n_states]-->[b,n_hiddens]x = self.fc2(x)  # [b,n_hiddens]-->[b,n_actions]return x# ----------------------------------- #
#(3)模型构建
# ----------------------------------- #class Double_DQN:#(1)初始化def __init__(self, n_states, n_hiddens, n_actions,learning_rate, gamma, epsilon,target_update, device):# 属性分配self.n_states = n_statesself.n_hiddens = n_hiddensself.n_actions = n_actionsself.learning_rate = learning_rateself.gamma = gammaself.epsilon = epsilonself.target_update = target_updateself.device = device# 记录迭代次数self.count = 0# 实例化训练网络self.q_net = Net(self.n_states, self.n_hiddens, self.n_actions)# 实例化目标网络self.target_q_net = Net(self.n_states, self.n_hiddens, self.n_actions)# 优化器,更新训练网络的参数self.optimizer = torch.optim.Adam(self.q_net.parameters(), lr=self.learning_rate)#(2)动作选择def take_action(self, state):# numpy[n_states]-->[1, n_states]-->Tensorstate = torch.Tensor(state[np.newaxis, :])# print('--------------------------')# print(state.shape)# 如果小于贪婪系数就取最大值reward最大的动作if np.random.random() < self.epsilon:# 获取当前状态下采取各动作的rewardactions_value = self.q_net(state)# 获取reward最大值对应的动作索引action = actions_value.argmax().item()# 如果大于贪婪系数就随即探索else:action = np.random.randint(self.n_actions)return action#(3)获取每个状态对应的最大的state_valuedef max_q_value(self, state):# list-->tensor[3]-->[1,3]state = torch.tensor(state, dtype=torch.float).view(1,-1)# 当前状态对应的每个动作的reward的最大值 [1,3]-->[1,11]-->intmax_q = self.q_net(state).max().item()return max_q#(4)网络训练def update(self, transitions_dict):# 当前状态,array_shape=[b,4]states = torch.tensor(transitions_dict['states'], dtype=torch.float)# 当前状态的动作,tuple_shape=[b]==>[b,1]actions = torch.tensor(transitions_dict['actions'], dtype=torch.int64).view(-1,1)# 选择当前动作的奖励, tuple_shape=[b]==>[b,1]rewards = torch.tensor(transitions_dict['rewards'], dtype=torch.float).view(-1,1)# 下一个时刻的状态array_shape=[b,4]next_states = torch.tensor(transitions_dict['next_states'], dtype=torch.float)# 是否到达目标 tuple_shape=[b,1]dones = torch.tensor(transitions_dict['dones'], dtype=torch.float).view(-1,1)# 当前状态[b,4]-->当前状态采取的动作及其奖励[b,2]-->actions中是每个状态下的动作索引# -->当前状态s下采取动作a得到的state_valueq_values = self.q_net(states).gather(1, actions)# 获取动作索引# .max(1)输出tuple每个特征的最大state_value及其索引,[1]获取的每个特征的动作索引shape=[b]max_action = self.q_net(next_states).max(1)[1].view(-1,1)# 下个状态的state_value。下一时刻的状态输入到目标网络,得到每个动作对应的奖励,使用训练出来的action索引选取最优动作max_next_q_values = self.target_q_net(next_states).gather(1, max_action)# 目标网络计算出的,当前状态的state_valueq_targets = rewards + self.gamma * max_next_q_values * (1-dones)# 预测值和目标值的均方误差损失dqn_loss = torch.mean(F.mse_loss(q_values, q_targets))# 梯度清零self.optimizer.zero_grad()# 梯度反传dqn_loss.backward()# 更新训练网络的参数self.optimizer.step()# 更新目标网络参数if self.count % self.target_update == 0:self.target_q_net.load_state_dict(self.q_net.state_dict())  # 更新目标网络# 迭代计数+1self.count += 1

3. 案例实现

我们使用 OpenAI 中的重力摆来验证模型,动作是连续型,代表力矩;状态包含三个;目的是让杆子竖直。

 环境交互和训练代码如下:

import torch
import numpy as np
import gym
from tqdm import tqdm
import matplotlib.pyplot as plt
from parsers import args
from RL_brain import ReplayBuffer, Double_DQN# GPU运算
device = torch.device("cuda") if torch.cuda.is_available() \else torch.device("cpu")# ------------------------------- #
#(1)加载环境
# ------------------------------- #env = gym.make("Pendulum-v1", render_mode="human")
n_states = env.observation_space.shape[0]  # 状态数 3
act_low = env.action_space.low  # 最小动作力矩 -2
act_high = env.action_space.high  # 最大动作力矩 +2
n_actions = 11  # 动作是连续的[-2,2],将其离散成11个动作# 确定离散动作区间后,确定其连续动作
def dis_to_con(discrete_action, n_actions):# discrete_action代表动作索引return act_low + (act_high-act_low) * (discrete_action/(n_actions-1))# 实例化经验池
replay_buffer = ReplayBuffer(args.capacity)# 实例化 Double-DQN
agent = Double_DQN(n_states,args.n_hiddens,n_actions,args.lr,args.gamma,args.epsilon,args.target_update,device)# ------------------------------- #
#(2)模型训练
# ------------------------------- #return_list = []  # 记录每次迭代的return,即链上的reward之和
max_q_value = 0  # 最大state_value
max_q_value_list = []  # 保存所有最大的state_valuefor i in range(10):  # 训练几个回合done = False  # 初始,未到达终点state = env.reset()[0]  # 重置环境episode_return = 0  # 记录每回合的returnwith tqdm(total=10, desc='Iteration %d' % i) as pbar:while True:# 状态state时做动作选择,返回索引action = agent.take_action(state)# 平滑处理最大state_valuemax_q_value = agent.max_q_value(state) * 0.005 + \max_q_value * 0.995# 保存每次迭代的最大state_valuemax_q_value_list.append(max_q_value)# 将action的离散索引连续化action_continuous = dis_to_con(action, n_actions)# 环境更新next_state, reward, done, _, _ = env.step(action_continuous)# 添加经验池replay_buffer.add(state, action, reward, next_state, done)# 更新状态state = next_state# 更新每回合的回报episode_return += reward# 如果经验池超数量过阈值时开始训练if replay_buffer.size() > args.min_size:# 在经验池中随机抽样batch组数据s, a, r, ns, d = replay_buffer.sample(args.batch_size)# 构造训练集transitions_dict = {'states': s,'actions': a,'next_states': ns,'rewards': r,'dones': d,}# 模型训练agent.update(transitions_dict)# 到达终点就停止if done is True: break# 保存每回合的returnreturn_list.append(episode_return)pbar.set_postfix({'step':agent.count,'return':'%.3f' % np.mean(return_list[-10:])})pbar.update(1)# ------------------------------- #
#(3)绘图
# ------------------------------- #plt.subplot(121)
plt.plot(return_list)
plt.title('return')
plt.subplot(122)
plt.plot(max_q_value_list)
plt.title('max_q_value')
plt.show()

相关文章:

【深度强化学习】(2) Double DQN 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和大家分享一个深度强化学习算法 DQN 的改进版 Double DQN&#xff0c;并基于 OpenAI 的 gym 环境库完成一个小游戏&#xff0c;完整代码可以从我的 GitHub 中获得&#xff1a; https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Model 1…...

【正则表达式】正则表达式语法规则

正则表达式语法规则1.普通字符 字符描述[ABC]匹配 […] 中的所有字符[^ABC]匹配除了 […] 中字符的所有字符[A-Z][A-Z] 表示一个区间&#xff0c;匹配所有大写字母&#xff0c;[a-z] 表示所有小写字母.匹配除换行符以外的任意字符[\s\S]匹配所有。\s 是匹配所有空白符&#xf…...

1636_isatty函数的功能

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 前面刚刚看完了一个函数和三个文件指针&#xff0c;一行代码懂了半行。但是继续分析我之前看到的代码还是遇到了困难&#xff0c;因为之前自己对于UNIX的一些基础知…...

基于Stackelberg博弈的光伏用户群优化定价模型(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

EXCEL职业版本(3)

Excel职业版本&#xff08;3&#xff09; 公式与函数 运算符 算数运算符 关系运算符 地址的引用 相对引用&#xff1a;你变它就变&#xff0c;如影随形 A2&#xff1a;A5 绝对引用&#xff1a;以不变应万变 $A$2 混合引用&#xff1a;识时务者为俊杰&#xff0c;根据时…...

查找Pycharm跑代码下载模型存放位置以及有关模型下载小技巧(model_name_or_path参数)

目录一、前言二、发现问题三、删除这些模型方法一&#xff1a;直接删除注意方法二&#xff1a;代码删除一、前言 当服务器连不上&#xff0c;只能在本地跑代码时需要使用***预训练语言模型进行处理 免不了需要把模型下载到本地 时间一长就会发现C盘容量不够 二、发现问题 正…...

JS学习笔记day04

今日内容 零、 复习昨日 一、事件 二、DOM操作 三、案例 零、 复习昨日 js 脚本语言,弱类型 引入方案: 3种 js的内容: 语法dombom 语法 变量 var 数据类型 引用类型 - 对象,JSON {key:value,key:value} 数组 var arr new Array();var arr [1,2];下标取值赋值pop() s…...

异步控制流程 遍历篇

文章目录基础方法onlyOnce 只执行一次&#xff0c;第二次报错once 只执行一次&#xff0c;第二次无效iteratorSymbol 判断是否具有迭代器并返回迭代器arrayEach 普通数组遍历baseEach 对象类型遍历symbolEach 具有迭代器类型遍历异步遍历each异步控制流程的目的&#xff1a; 对…...

ICASSP 2023论文模型开源|语音分离Mossformer

人类能在复杂的多人说话环境中轻易地分离干扰声音&#xff0c;选择性聆听感兴趣的主讲人说话。但这对机器却不容易&#xff0c;如何构建一个能够媲美人类听觉系统的自动化系统颇具挑战性。 本文将详细解读ICASSP2023本届会议收录的单通道语音分离模型Mossformer论文&#xff0…...

vs2019 更改工程项目名称

本地 解决方案所在的位置为&#xff1a;D:\Projcet 解决方案名称&#xff1a;hello.sln 位置&#xff1a;D:\Projcet\hello.sln 工程项目名称&#xff1a;test 位置&#xff1a;D:\Projcet\test (文件夹中包含头文件&#xff0c;源文件) 工程包含的文件&#xff1a; fun.h …...

FusionCompute安装和配置步骤

1. 先去华为官网下载FusionCompute的镜像 下载地址&#xff1a;https://support.huawei.com/enterprise/zh/distributed-storage/fusioncompute-pid-8576912/software/251713663?idAbsPathfixnode01%7C22658044%7C7919788%7C9856606%7C21462752%7C8576912 下载后放在D盘中&am…...

makefile 参数和基本使用

make 常用选项make[-f file] [options] [target]make 默认在当前目录中查找GUNmakefile、makefile 及 Makefile 文件作为make的输入文件-f 指定文件作为输入文件-v 显示版本号-n 只输出命令不执行&#xff0c; 一般作为测试-s 执行命令不显示命令&#xff0c;-w 显示执行前和执…...

golang 占位符还傻傻分不清?

xdm &#xff0c;写 C/C 语言的时候有格式控制符&#xff0c;例如 %s , %d , %c , %p 等等 在写 golang 的时候&#xff0c;也是有对应的格式控制符&#xff0c;也叫做占位符&#xff0c;写这个占位符&#xff0c;需要有对应的数据与之对应&#xff0c;不能瞎搞 基本常见常用…...

manacher算法详解

例题 求一个字符串的最长回文子串的长度 O(N2)O(N^2)O(N2)的解法很容易想&#xff0c;就是从每个字符位置向左右同时拓展&#xff0c;然后检查当前是不是回文&#xff0c;更新长度&#xff0c;可以简单写一下代码 int solve(string &ss){int ans 0;int n ss.length();s…...

要做一个关于DDD的内部技术分享,记录下用到的资源,学习笔记(未完)

最后更新于2023年3月10日 14:28:08 问题建模》软件分层》具体结构&#xff0c;是层层递进的关系。有了问题建模&#xff0c;才能进行具体的软件分层的讨论&#xff0c;再有了分层&#xff0c;才能讨论在domain里面应该怎么实现具体结构。 1、问题建模&#xff1a;Domain、Mod…...

KDZD互感器二次负载测试仪

一、概述 电能计量综合误差过大是电能计量中普遍存在的一个关键问题。电压互感器二次回路压降引起的计量误差往往是影响电能计量综合误差的因素。所谓电压互感器二次压降引起的误差&#xff0c;就是指电压互感器二次端子和负载端子之间电压的幅值差相对于二次实际电压的百分数…...

在空投之后,Blur能否颠覆OpenSea的主导地位?

Mar. 2023, Daniel数据源&#xff1a; NFT Aggregators Overview & Aggregator Statistics Overview & Blur Airdrop一年前&#xff0c;通过聚合器进行的NFT交易量开始像滚雪球一样增长&#xff0c;有时甚至超过了直接通过市场平台的交易量。虽然聚合器的使用量从10月到…...

2023年新三板产品及服务研究报告

第一章 概述 全国中小企业股份转让系统&#xff08;英语&#xff1a;National Equities Exchange and Quotations&#xff0c;缩写NEEQ&#xff09;&#xff0c;简称股转系统&#xff0c;是第三家全国性证券交易场所&#xff0c;因挂牌企业均为高科技企业而不同于原转让系统内…...

张力控制之开环模式

张力控制的相关知识也可以参看专栏的其它文章,链接如下: 张力闭环控制之传感器篇(精密调节气阀应用)_RXXW_Dor的博客-CSDN博客跳舞轮对应张力调节范围,我们可以通过改变气缸的气压方式间接改变,张力跳舞轮在收放卷闭环控制上的详细应用,可以参看下面的文章链接,这里我…...

python的django框架从入门到熟练【保姆式教学】第二篇

在上一篇博客中&#xff0c;我们介绍了Django的基础知识&#xff0c;并创建了一个简单的Web应用程序。在本篇教程中&#xff0c;我们将深入探讨Django的模型层&#xff08;Model&#xff09;&#xff0c;它是Django应用程序的核心组件之一。 模型层 Django的模型层是一个对象…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

uniapp获取当前位置和经纬度信息

1.1. 获取当前位置和经纬度信息&#xff08;需要配置高的SDK&#xff09; 调用uni-app官方API中的uni.chooseLocation()&#xff0c;即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...

智能体革命:企业如何构建自主决策的AI代理?

OpenAI智能代理构建实用指南详解 随着大型语言模型&#xff08;LLM&#xff09;在推理、多模态理解和工具调用能力上的进步&#xff0c;智能代理&#xff08;Agents&#xff09;成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同&#xff0c;智能代理能够自主执行工…...