游戏AI的创造思路-技术基础-强化学习(1)

我们“强化”一下机器的“学习”,让机器变得更强~~~~

目录

1. 强化学习的定义

2. 发展历史

3. 强化学习的基本概念和函数

3.1. 基本概念和函数

3.1.1. 基本概念和函数

3.1.2. Q函数

3.1.2.1. 定义与作用

3.1.2.2. 数学表示

3.1.2.3. 更新规则

3.1.2.4. 算法应用

3.1.2.5. 应用领域

3.1.2.6. Q函数小总结

3.1.3. 价值函数

3.1.3.1. 定义与分类

3.1.3.2. 作用与意义

3.1.3.3. 更新与优化

3.1.3.3.1. 贝尔曼方程

3.1.3.3.1.1. 贝尔曼方程的定义

3.1.3.3.1.2. 贝尔曼方程的类型

3.1.3.3.1.3. 价值函数的更新与优化

3.1.3.3.1.4. 应用实例

3.1.3.3.1.5. 贝尔曼方程小总结

3.1.3.3.2. 深度强化学习

3.1.3.4. 应用领域

3.1.3.5. 价值函数小总结

3.2. Python代码示例

3. 运行原理

4. 优缺点

5. 游戏AI中的使用场景和实例

5.1. 场景

5.2. 实例


1. 强化学习的定义

强化学习(Reinforcement Learning, RL)是机器学习的一个分支,关注的是智能体(agent)如何在环境中采取行动以最大化某种累积奖励(reward)。智能体通过与环境交互来学习如何完成任务,环境对智能体的每一个动作给出一个奖励或惩罚,智能体的目标是最大化总的奖励。

2. 发展历史

强化学习的思想可以追溯到控制论和优化理论,但直到1980年代和1990年代,随着计算能力的提升和算法的发展,它才开始受到广泛关注。在2010年代,由于深度学习技术的结合,强化学习在处理复杂问题,如游戏和机器人控制方面取得了显著进展。

3. 强化学习的基本概念和函数

3.1. 基本概念和函数

3.1.1. 基本概念和函数

强化学习通常涉及到几个关键概念和函数:

  • 状态(State):智能体所处的环境。
  • 动作(Action):智能体可以采取的行为。
  • 奖励(Reward):环境对智能体动作的反馈。
  • 策略(Policy):智能体选择动作的策略。
  • 价值函数(Value Function):预测状态或动作状态对的长期价值。
  • Q函数(Q-Function):给定状态下,采取特定动作的预期效用。

其中,以下我们讨论下Q函数和价值函数

3.1.2. Q函数

强化学习中的Q函数是强化学习算法中的一个核心概念,尤其在基于价值函数的强化学习算法中扮演着至关重要的角色。以下是对Q函数的详细介绍:

3.1.2.1. 定义与作用

Q函数,也称为Q值函数,用于计算智能体(agent)在某个状态下采取某个动作后所预期的累计回报。它是强化学习中实现智能体学习最优策略以最大化期望回报的关键工具。Q函数的值即为在特定状态下采取特定动作所能获得的期望回报,这有助于智能体在面临决策时选择最优动作。

3.1.2.2. 数学表示

Q函数可以用数学公式表示为:

[ Q(s, a) = E[R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + \ldots | S_t = s, A_t = a] ]

其中,

  • (s)表示当前的状态。
  • (a) 表示智能体采取的动作。
  • (R_t)表示在(t)时刻获得的即时奖励。
  • (\gamma)是一个介于0和1之间的折扣因子,用于平衡即时奖励和未来奖励的重要性。

这个公式表示了在状态(s)下采取动作(a)后,从当前时刻开始所能获得的期望累积回报。

3.1.2.3. 更新规则

Q函数的值不是固定不变的,而是通过智能体与环境的不断交互来动态更新的。Q函数的更新规则通常采用贝尔曼方程的形式:

[ Q(s, a) \leftarrow Q(s, a) + \alpha [R + \gamma \max_{a'}(Q(s', a')) - Q(s, a)] ]

其中,

  • (\alpha)是学习率,控制每次更新的步长大小。
  • (s')(a')分别表示下一个状态和动作。
  • (\max_{a'}(Q(s', a')))表示在下一个状态(s')下采取所有可能的动作中,期望回报最大的值。

这个更新规则意味着,智能体在每次与环境交互后,会根据观察到的即时奖励和下一个状态来更新Q函数的值,以便更好地估计未来回报。

3.1.2.4. 算法应用

Q函数在强化学习中有着广泛的应用,尤其是在解决马尔可夫决策过程(MDP)问题时。

其中,Q学习算法是最著名的基于Q函数的强化学习算法之一。

它通过不断地与环境交互、更新Q函数值来选择最优策略。

此外,深度Q网络(DQN)等深度强化学习算法也利用了Q函数的思想,通过神经网络来逼近Q函数以处理高维状态空间和动作空间的问题。

3.1.2.5. 应用领域

Q函数在多个领域具有广泛应用,包括但不限于:

  • 机器人控制:在机器人控制中,Q函数可以帮助智能体计算在当前状态下采取哪些动作能够使其达到目标位置并获得最大的期望回报。
  • 游戏智能体:在游戏智能体中,Q函数可以帮助智能体计算在当前状态下采取哪些动作能够获得最高的得分。
  • 自动驾驶:在自动驾驶领域,Q函数可以用于指导车辆在不同交通状况下的最优驾驶策略。
  • 推荐系统:在推荐系统中,Q函数可以用于评估不同推荐策略的效果,从而优化推荐算法的性能。
3.1.2.6. Q函数小总结

Q函数是强化学习中实现智能体学习最优策略的重要工具之一。

通过不断更新Q函数的值,智能体能够逐渐了解到在不同状态下采取不同动作的价值,并选择具有最高Q值的动作以实现最大化期望回报的目标。

3.1.3. 价值函数

强化学习中的价值函数是评估智能体(agent)在不同状态下或采取不同动作后所能获得的长期回报预期的重要工具。以下是对价值函数的详细介绍:

3.1.3.1. 定义与分类

在强化学习中,价值函数用于衡量智能体在给定状态下或采取特定动作后,通过遵循某个策略所能获得的预期累积奖励。根据评估对象的不同,价值函数主要分为两类:

3.1.3.1.1. 状态价值函数(State-Value Function)

记作V(s),表示在状态s下,智能体遵循某一策略时所能获得的长期回报的期望值。它衡量的是智能体处于某个状态时的优劣程度。

3.1.3.1.2. 动作价值函数(Action-Value Function 或 Q 函数)

记作Q(s, a),表示在状态s下执行动作a后,智能体遵循某一策略时所能获得的长期回报的期望值。它衡量的是在特定状态下采取某个动作的优劣程度。

3.1.3.2. 作用与意义

价值函数在强化学习中起到了至关重要的作用,主要体现在以下几个方面:

  1. 决策指导:价值函数为智能体提供了在不同状态下或面对不同动作选择时的决策依据。通过比较不同状态下的价值或不同动作的价值,智能体可以选择最优策略以实现目标最大化。

  2. 策略优化:基于价值函数的估计,智能体可以不断改进其策略,选择具有更高价值的动作来执行,从而获得更高的预期累积奖励。

  3. 长期回报评估:价值函数能够估计智能体在长期交互过程中可能获得的回报,而不仅仅是即时奖励,这使得智能体能够做出更具有前瞻性的决策。

3.1.3.3. 更新与优化

价值函数的更新和优化是强化学习算法的核心任务之一。常见的更新方法包括使用贝尔曼方程进行迭代更新,以及结合深度学习算法(如DQN)来逼近复杂的价值函数。

3.1.3.3.1. 贝尔曼方程

贝尔曼方程是强化学习中用于递归计算价值函数的重要工具。对于状态价值函数V(s)和动作价值函数Q(s, a),它们的贝尔曼方程分别表示了如何通过当前状态的价值和后继状态的价值来更新当前状态的价值。

在强化学习中,价值函数的更新与优化是一个核心过程,它直接关系到智能体(agent)能否学习到最优策略以最大化长期回报。贝尔曼方程在这一过程中起到了至关重要的作用,它提供了一种递归计算价值函数的方法。以下是对贝尔曼方程在价值函数更新与优化中的详细介绍:

3.1.3.3.1.1. 贝尔曼方程的定义

贝尔曼方程是强化学习中用于描述状态价值函数或动作价值函数之间关系的数学公式。它表明了一个状态(或状态-动作对)的价值可以通过其后继状态(或状态-动作对)的价值来计算。

3.1.3.3.1.2. 贝尔曼方程的类型

根据评估对象的不同,贝尔曼方程可以分为两类:

状态价值函数的贝尔曼方程

[ V(s) = E[R_{t+1} + \gamma V(S_{t+1}) | S_t = s] ]

其中,(V(s))表示状态(s)的价值函数,(R_{t+1}) 表示在(t+1)时刻获得的即时奖励,(\gamma)是折扣因子,(S_{t+1}) 表示下一个状态,(E)表示期望值。这个方程表明状态(s)的价值等于从该状态出发所有可能后继状态的价值的期望加权和。

动作价值函数的贝尔曼方程

[ Q(s, a) = E[R_{t+1} + \gamma \max_{a'} Q(S_{t+1}, a') | S_t = s, A_t = a] ]

其中,(Q(s, a))表示在状态 (s)下采取动作(a)的价值函数,其余符号的含义与状态价值函数的贝尔曼方程相同。这个方程表明在状态 (s) 下采取动作(a) 的价值等于采取该动作后获得的即时奖励加上所有可能后继状态下采取最优动作的价值的期望加权和。

3.1.3.3.1.3. 价值函数的更新与优化

在强化学习过程中,智能体通过与环境的交互来收集数据,并利用这些数据来更新价值函数的估计值。贝尔曼方程提供了一种递归更新价值函数的方法,使得智能体能够逐渐逼近真实的价值函数。

更新规则

对于状态价值函数,更新规则通常可以表示为:

[ V(s) \leftarrow V(s) + \alpha [R_{t+1} + \gamma V(S_{t+1}) - V(s)] ]

其中,(\alpha)是学习率,用于控制更新的步长。

对于动作价值函数,更新规则类似,但需要考虑动作的选择:

[ Q(s, a) \leftarrow Q(s, a) + \alpha [R_{t+1} + \gamma \max_{a'} Q(S_{t+1}, a') - Q(s, a)] ]

优化方法

  • 动态规划:在已知环境模型的情况下,可以使用动态规划方法来迭代更新价值函数,直到收敛到最优解。
  • 蒙特卡洛方法:通过多次采样完整的交互轨迹来估计价值函数,不需要环境模型。
  • 时序差分学习:结合了动态规划和蒙特卡洛方法的优点,通过单步或多步的交互数据来更新价值函数。
  • 深度强化学习:使用深度神经网络来逼近价值函数,并通过反向传播算法来优化网络参数。
3.1.3.3.1.4. 应用实例

贝尔曼方程在强化学习中的应用非常广泛,几乎所有的基于价值函数的强化学习算法都会用到它。例如,Q学习算法和深度Q网络(DQN)就是基于动作价值函数的贝尔曼方程来更新和优化价值函数的。这些算法通过不断地与环境交互来收集数据,并利用贝尔曼方程来更新价值函数的估计值,从而逐步逼近最优策略。

3.1.3.3.1.5. 贝尔曼方程小总结

贝尔曼方程是强化学习中价值函数更新与优化的关键工具,它提供了一种递归计算价值函数的方法,使得智能体能够通过与环境的交互来学习到最优策略。

3.1.3.3.2. 深度强化学习

在深度强化学习中,深度神经网络被用来逼近复杂的价值函数。例如,在DQN算法中,一个深度神经网络被训练来预测动作价值函数Q(s, a),并通过与环境的交互来不断更新网络参数以优化价值函数的估计。

深度强化学习是一个大类,我们在后面的篇章中进行介绍,这里暂时留个坑待填~~~

3.1.3.4. 应用领域

价值函数在多个领域具有广泛应用,包括但不限于:

  1. 机器人控制:通过优化价值函数,机器人可以学习到在不同环境下采取最优动作的策略,从而实现自主导航、物体抓取等任务。

  2. 游戏智能体:在游戏领域,价值函数被用于指导智能体(如AlphaGo)在复杂游戏环境中做出决策,以赢得比赛或获得最高得分。

  3. 金融交易:在金融交易领域,基于强化学习的价值函数优化技术可以实现智能化的交易决策和风险管理,提高交易效率和收益。

3.1.3.5. 价值函数小总结

价值函数是强化学习中的核心概念之一,它通过评估智能体在不同状态下的长期回报预期来指导智能体的决策过程,并在多个领域具有广泛应用前景。随着深度学习和强化学习技术的不断发展,我们有理由相信价值函数将在未来发挥更加重要的作用。

3.2. Python代码示例

这里是一个简单的Q学习算法的实现,Q学习是一种常用的强化学习算法:

import numpy as np  
import random  # 初始化环境  
class Environment:  def __init__(self):  self.states = ['state1', 'state2', 'state3']  self.actions = ['action1', 'action2']  self.rewards = {  ('state1', 'action1'): 1,  ('state1', 'action2'): 2,  ('state2', 'action1'): 2,  ('state2', 'action2'): 1,  ('state3', 'action1'): 0,  ('state3', 'action2'): 0  }  def step(self, state, action):  next_state = random.choice(self.states)  reward = self.rewards[(state, action)]  return next_state, reward  # Q学习  
def q_learning(env, episodes=1000, alpha=0.1, gamma=0.99):  q_table = {state: {action: 0 for action in env.actions} for state in env.states}  for _ in range(episodes):  state = random.choice(env.states)  while True:  action = max(q_table[state], key=q_table[state].get)  next_state, reward = env.step(state, action)  q_table[state][action] = (1 - alpha) * q_table[state][action] + alpha * (reward + gamma * max(q_table[next_state].values()))  state = next_state  if state == 'terminal_state':  break  return q_table  env = Environment()  
q_table = q_learning(env)  
print(q_table)

3. 运行原理

  1. 初始化:创建一个Q表,用来存储每个状态下采取每个动作的预期效用。
  2. 选择动作:根据当前的Q表和状态选择一个动作。
  3. 执行动作:执行选择的动作,并观察奖励和新的状态。
  4. 更新Q表:根据观察到的奖励和新的状态更新Q表。

以下是强化学习(特别是Q学习)运行原理中各个步骤的详细Python代码:

import numpy as np  
import random  # 定义游戏环境  
class Game:  def __init__(self):  self.states = range(10)  # 状态空间为0到9  self.actions = [0, 1]    # 可行的动作,0代表“不动”,1代表“前”  def step(self, state, action):  # 执行动作并返回下一个状态和奖励  if action == 1:  next_state = min(state + 1, 9)  else:  next_state = state  reward = 1 if next_state == 9 else 0  return next_state, reward  # Q学习算法  
def q_learning(env, episodes=1000, alpha=0.1, gamma=0.99):  # 初始化Q表  q_table = {state: {action: 0 for action in env.actions} for state in env.states}  for _ in range(episodes):  state = random.choice(env.states)  # 从任意状态开始  while True:  # 选择动作:根据当前的Q表和状态选择一个动作(这里使用贪心策略)  action = max(q_table[state], key=q_table[state].get)  # 执行动作  next_state, reward = env.step(state, action)  # 更新Q表  q_table[state][action] = (1 - alpha) * q_table[state][action] + \  alpha * (reward + gamma * max(q_table[next_state].values()))  # 移动到下一个状态  state = next_state  # 如果达到终止状态,则结束本轮迭代  if state == 9:  break  return q_table  # 创建游戏环境  
env = Game()  
# 训练游戏AI  
q_table = q_learning(env)  
# 打印训练后的Q表  
print(q_table)

在这段代码中,强化学习的运行原理被明确地分为以下几个步骤:

  1. 初始化
    • 创建一个Q表,用于存储每个状态下采取每个动作的预期效用。Q表的初始值通常设置为0。
  2. 选择动作
    • 根据当前的Q表和状态选择一个动作。这里使用了贪心策略,即选择当前状态下具有最高预期效用的动作。
  3. 执行动作
    • 在游戏环境中执行所选的动作,并观察下一个状态和奖励。
  4. 更新Q表
    • 使用Q学习的更新规则来更新Q表中的值。更新规则考虑了当前动作的奖励、下一个状态的预期效用以及学习率(alpha)和折扣因子(gamma)。
  5. 移动到下一个状态
    • 将当前状态更新为下一个状态,并继续选择和执行动作,直到达到终止状态或完成一轮迭代。

通过重复这些步骤,Q学习算法能够逐渐学习到最优策略,即每个状态下应该采取的动作以最大化长期奖励。

 

4. 优缺点

优点

  • 能在没有环境模型的情况下学习。
  • 可以在线学习,适应动态变化的环境。

缺点

  • 可能需要大量的样本才能学习到有效的策略。
  • 对于复杂问题,学习可能非常慢。(不是一般的慢,是真的慢,学习一个小人跳过障碍10块4090就干了1周多才勉勉强强跳过)

5. 游戏AI中的使用场景和实例

5.1. 场景

强化学习在游戏AI中广泛使用,例如:

  • AlphaGo:使用强化学习来训练下棋策略。
  • 游戏角色控制:使用强化学习来训练游戏中的角色如何行动以最大化游戏得分。

5.2. 实例

实例代码(简化版):

下面是一个完整的实例代码,展示了如何使用强化学习(特别是Q学习)来训练一个简单的游戏AI。

在这个例子中,游戏的目标是达到一个特定的状态(例如状态9),在达到该状态时,游戏会给予奖励。

import numpy as np  
import random  # 定义游戏环境  
class Game:  def __init__(self):  self.states = range(10)  # 状态空间为0到9  self.actions = [0, 1]    # 可行的动作,这里简化为0和1,分别代表向“前”移动一步或保持不动(在这个简单例子中,实际上只有“前”是有效的)  def step(self, state, action):  # 执行动作并返回下一个状态和奖励  if action == 1:  # 假设动作1是“前”  next_state = min(state + 1, 9)  # 确保不会超出状态空间  else:  next_state = state  # 动作0是“保持不动”  reward = 1 if next_state == 9 else 0  # 只有达到状态9时才给予奖励  return next_state, reward  # Q学习算法  
def q_learning(env, episodes=1000, alpha=0.1, gamma=0.99):  q_table = {state: {action: 0 for action in env.actions} for state in env.states}  for _ in range(episodes):  state = random.choice(env.states)  # 从任意状态开始  while True:  # 选择当前状态下最优的动作  action = max(q_table[state], key=q_table[state].get)  # 执行动作并获取下一个状态和奖励  next_state, reward = env.step(state, action)  # 更新Q表  q_table[state][action] = (1 - alpha) * q_table[state][action] + alpha * (reward + gamma * max(q_table[next_state].values()))  state = next_state  # 如果达到终止状态,则结束本轮迭代  if state == 9:  break  return q_table  # 创建游戏环境  
env = Game()  
# 训练游戏AI  
q_table = q_learning(env)  
# 打印训练后的Q表  
print(q_table)

这个例子中的游戏环境非常简单,只是为了展示如何应用强化学习。在实际的游戏中,环境和状态会更加复杂。

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

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

相关文章

AI时代算法面试:揭秘高频算法问题与解答策略

三种决策树算法的特点和区别 ID3算法:基本的决策树算法,适用于简单的分类问题C4.5算法:改进了ID3算法,适用于更复杂的分类问题,可以处理连续型数据和缺失值CART算法:更加通用的决策树算法,适用于…

云服务器在 Web 应用程序中作用

云服务器在Web应用程序中扮演着至关重要的角色,它不仅是现代Web应用程序的基石,还是推动业务发展和提升用户体验的关键技术之一。下面将详细探讨云服务器在Web应用程序中的重要作用及其优势。 首先,云服务器为Web应用程序提供了高度可扩展的…

【postgresql】索引

见的索引类型: B-tree 索引:这是最常用的索引类型,适用于大多数查询。B-tree索引可以高效地处理范围查询。 Hash 索引:适用于等值查询,但不支持范围查询。 GiST 索引:通用搜索树(GiST&#xf…

怀念旧的Windows声音?以下是如何在Windows 11中恢复它们

如果你渴望旧的Windows声音,希望能在Windows 11上再次听到,那你就很幸运了。我们将向你展示如何下载必要的声音包并创建复古的声音方案。 如何获取旧Windows声音的声音包 你需要做的第一件事是下载一个包含旧Windows版本声音的声音包。此外,请确保它包含的每个声音都是WAV…

在 Vue 项目中使用 FullCalendar

1、先安装依赖包,根据自己的需求安装,建议使用cnpm安装,不然会很慢有时候会出现安装不上的情况。 npm i fullcalendar/vue --save npm i fullcalendar/core --save // 在月视图或日视图中操作事件 npm i fullcalendar/daygrid --save // 在…

记录discuz修改用户的主题出售价格

大家好,我是网创有方的站长,今天遇到了需要修改discuz的主题出售价格。特此记录下 方法很简单: 进入用于组-》选择论坛-》批量修改

【shell编程小项目】

目录 一、项目拓扑二、要求三、shell编程 一、项目拓扑 二、要求 环境准备: 准备两个虚拟机,按照环境配置好对应的 IP 地址和对应的主机名和 SSH 密钥登录在 workstation.exam.com 节点实现如下需求: 1、编写 Shell 脚本,要求代码…

0803实操-Windows Server系统管理

Windows Server系统管理 系统管理与基础配置 查看系统信息、更改计算机名称 网络配置 启用网络发现 Windows启用网络发现是指在网络设置中启用一个功能,该功能允许您的计算机在网络上识别和访问其他设备和计算机。具体来说,启用网络发现后&#xff…

Qt5.9.9 关于界面拖动导致QModbusRTU(QModbusTCP没有测试过)离线的问题

问题锁定 参考网友的思路: Qt5.9 Modbus request timeout 0x5异常解决 网友认为是Qt的bug, 我也认同;网友认为可以更新模块, 我也认同, 我也编译了Qt5.15.0的code并成功安装到Qt5.9.9中进行使用,界面拖…

Mybatis原生使用

一、MyBatis初次使用 2.1 环境搭建步骤 MyBatis 的 API : https://mybatis.org/mybatis-3/zh/getting-started.html 1.引入依赖包 2.准备核心配置件 db.properties drivercom.mysql.cj.jdbc.Driver urljdbc:mysql://123.57.206.19:3306/demo?useUnicodetrue&am…

如何选择最佳的照片和视频恢复软件

您是否意外从硬盘或 USB 卡中删除了照片或视频?最好的视频和照片恢复软件可以帮到您!如果您一直在寻找最好的照片恢复软件,那么您来对地方了。本文将分享一些帮助您找到最佳视频恢复软件的提示。 重要提示:事实:媒体文…

【LabVIEW学习篇 - 3】:程序结构——顺序结构、for循环、while循环

文章目录 顺序结构案例一案例二 for循环while循环 顺序结构 LabVIEW中的顺序结构是一种常用的控制结构,用于按顺序执行程序的不同部分。顺序结构在程序中按照从左到右的顺序依次执行各个子结构,类似于传统的文本编程语言中的顺序执行。 案例一 案例一…

JAVA的线性表数据结构的超详解

目录 顺序表的顺序存储结构 1.数组 2.顺序表 顺序表的声明,存储操作以及效率分析 1.泛型类 2.顺序表的插入操作 3. 顺序表的删除操作 4.顺序表查询操作 5.顺序表的应用 线性表的链式存储结构 单链表的基本操作 顺序表的顺序存储结构 数组是实现顺序存储…

随手记录: Ubuntu NVIDIA显卡驱动安装后 屏幕亮度无法调节 无法连接外显示器等问题

背景 一句话:简单记录帮身边人装系统发现 GPU和外接显示器的无法连接,同时亮度无法调节等新问题 设备型号: 联想笔记本:ThinkBook 16p Gen2CPU:AMD Ryzen 7 5800HGPU:RTX 3060 问题描述及流程&#xff…

类继承-多继承虚继承

#include<iostream> using namespace std; class A1 { public:int a 10;}; class A2 { public:int b 20; }; class B :public A1, public A2 { public:int c 30; }; int main(){B b;cout << b.a << b.b << b.c << endl;return 0; } 如果基类…

STM32-HAL-SDIO-(sd卡的识别,整理后的版本)

1STM32Cube操作 1-1配置时钟 1-2配置调试端口 1-3配置uart 1-4配置SDIO 选择数据传输引脚个数 需改配置&#xff08;图中改了两处&#xff0c;选中的和最后一个&#xff09; 1-5打开DMA 传输方向改为图中的&#xff08;由内转向外设&#xff09;在改图中的一次读写的大小 1-…

图像处理调试软件推荐

对于图像处理的调试&#xff0c;使用具有图形用户界面&#xff08;GUI&#xff09;且支持实时调整和预览的图像处理软件&#xff0c;可以大大提高工作效率。以下是几款常用且功能强大的图像处理调试软件推荐&#xff1a; ImageJ/FijiMATLABOpenCV with GUI LibrariesNI Vision …

Java中关于构造代码块和静态代码块的解析

构造代码块 特点&#xff1a;优先于构造方法执行,每new一次,就会执行一次 public class Person {public Person(){System.out.println("我是无参构造方法");}{System.out.println("我是构造代码块"); //构造代码块} }public class Test {public stati…

【推荐图书】深入浅出Spring Boot 3.x

推荐原因 这部SpringBoot3.x经典之作&#xff0c;时隔六年迎来重磅升级&#xff01; 适合java开发相关读者 购买链接 商品链接&#xff1a;https://item.jd.com/14600442.html 介绍 书名&#xff1a;深入浅出Spring Boot 3.x ISBN&#xff1a;978-7-115-63282-1/ 作者&…

「ETL趋势」分区支持PostgreSQL、Greenplum、Gauss200, 定时任务支持Kettle

FineDataLink作为一款市场上的顶尖ETL工具&#xff0c;集实时数据同步、ELT/ETL数据处理、数据服务和系统管理于一体的数据集成工具&#xff0c;进行了新的维护迭代。本文把FDL4.1.9最新功能作了介绍&#xff0c;方便大家对比&#xff1a;&#xff08;产品更新详情&#xff1a;…