动手强化学习(六):DQN 算法

简介: 在车杆环境中,有一辆小车,智能体的任务是通过左右移动保持车上的杆竖直,若杆的倾斜度数过大,或者车子离初始位置左右的偏离程度过大,或者坚持时间到达 200 帧,则游戏结束。智能体的状态是一个维数为 4 的向量,每一维都是连续的,其动作是离散的,动作空间大小为 2,详情参见表 7-1 和表 7-2。在游戏中每坚持一帧,智能体能获得分数为 1 的奖励,坚持时间越长,则最后的分数越高,坚持 200 帧即可获得最高的分数。

文章转于 伯禹学习平台-动手学强化学习 (强推)


本文所有代码均可在jupyter notebook运行


与君共勉,一起学习。


1. 简介


 在前面讲解讲解的 Q-learning 算法中,我们以矩阵的方式建立了一张存储每个状态下所有动作 Q 值的表格。表格中的每一个动作价值 Q ( s , a )表示在状态 s 下选择动作 a 然后继续遵循某一策略预期能 够得到的期望回报。然而,这种用表格存储动作价值的做法只在环境的状态和动作都是离散的,并且空间都比较小的情况下适用,我们之前进行代码实战的几个环境都是如此 (如悬崖漫步) 。当 状态或者动作数量非常大的时候,这种做法就不适用了。例如,当状态是一张 RGB 图像时,假设图像大小是 210 × 160 × 3,此时一共有 25 6 ( 210 × 60 × 3 ) 种状态,在计算机中存储这个数量级的 Q 值 表格是不现实的。更甚者,当状态或者动作连续的时候,就有无限个状态动作对,我们更加无法使用这种表格形式来记录各个状态动作对的 Q 值。


对于这种情况,我们需要用函数拟合的方法来估计 Q 值,即将这个复杂的 Q 值表格视作数据,使用一个参数化的函数 Q θ 来拟合这些数据。很显然,这种函数拟合的方法存在一定的精度损失,因此 被称为近似方法。我们今天要介绍的 DQN 算法便可以用来解决连续状态下离散动作的问题。


2. CartPole 环境


以图 7-1 中所示的所示的车杆(CartPole)环境为例,它的状态值就是连续的,动作值是离散的。


d324d1ce09d9ffb9f715328343866a27.gif


在车杆环境中,有一辆小车,智能体的任务是通过左右移动保持车上的杆竖直,若杆的倾斜度数过大,或者车子离初始位置左右的偏离程度过大,或者坚持时间到达 200 帧,则游戏结束。智能体的状态是一个维数为 4 的向量,每一维都是连续的,其动作是离散的,动作空间大小为 2,详情参见表 7-1 和表 7-2。在游戏中每坚持一帧,智能体能获得分数为 1 的奖励,坚持时间越长,则最后的分数越高,坚持 200 帧即可获得最高的分数。


在车杆环境中,有一辆小车,智能体的任务是通过左右移动保持车上的杆竖直,若杆的倾斜度数过大,或者车子离初始位置左右的偏离程度过大,或者坚持时间到达 200 帧,则游戏结束。智能体的状态是一个维数为 4 的向量,每一维都是连续的,其动作是离散的,动作空间大小为 2,详情参见表 7-1 和表 7-2。在游戏中每坚持一帧,智能体能获得分数为 1 的奖励,坚持时间越长,则最后的分数越高,坚持 200 帧即可获得最高的分数。


753e00f90c514f9099f8840944157158.png


3. DQN


现在我们想在类似车杆的环境中得到动作价值函数 Q ( s , a )  ,由于状态每一维度的值都是连续的,无法使用表格记录,因此一个常见的解决方法便是使用函数拟合 (function approximation) 的思想。由于神经网络具有强大的表达能力,因此我们可以用一个神经网络来表示函数 Q  。若动作是连续 (无限) 的,神经网络的输入 是状态 s和动作 a ,然后输出一个标量,表示在状态 s 下采取动作 a 能获得的价值。若动作是离散(有限)的,除了可以采取动作连续情况下的做法,我们还可以只将 状态 s  输入到神经网络中,使其同时输出每一个动作的 Q  值。通常 DQN (以及 Q-learning) 只能处理动作离散的情况,因为在函数 Q  的更新过程中有max max 2 这操 作。假设神经网络用来拟合函数 ω 的参数是,即每一个状态 s下所有可能动作 a 的 Q 值我们都能表示为 Q ω ( s , a ) 。我们将用于拟合函数 Q  函数的神经网络称为 Q 网 络,如图 7-2 所示。


4ec279f5bc4540a98f6620ac44083701.png


那么 Q 网络的损失函数是什么呢? 我们先来回顾一下 Q-learning 的更新规则 :


image.png


上述公式用时序差分 (temporal difference,TD) 学习目标 r + γ max ⁡ a ′ ∈ A Q ( s ′ , a ′ ) 来增量式更新 Q ( s , a ) ,也就是说要使 Q ( s , a )  和 TD 目标 r + γ max a ′ ∈ A Q ( s ′ , a ′ ) 靠近。于是,对于一组数据 { ( s i , a i , r i , s' i )},我们可以很自然地将 Q 网络的损失函数构造为均方误差的形式:


image.png


至此,我们就可以将 Q-learning 扩展到神经网络形式—一深度 Q 网络(deep Q network,DQN) 算法。由于 DQN 是离线策略算法,因此我们在收集数据的时候可以使用一个 ϵ -贪婪策略来平衡 探索与利用,将收集到的数据存储起来,在后续的训练中使用。DQN 中还有两个非常重要的模块一经验回放和目标网络,它们能够帮助 DQN 取得稳定、出色的性能。


3.1 经验回放


在一般的有监督学习中,假设训练数据是独立同分布的,我们每次训练神经网络的时候从训练数据中随机采样一个或若干个数据来进行梯度下降,随着学习的不断进行,每一个训练数据会被使用 多次。在原来的 Q-learning 算法中,每一个数据只会用来更新一次 Q  值。为了更好地将 Q-learning 和深度神经网络结合, DQN 算法采用了经验回放(experience replay)方法,具体做法为维护 一个回放缓冲区,将每次从环境中采样得到的四元组数据(状态、动作、奖励、下一状态)存储到回放缓冲区中,训练 Q 网络的时候再从回放缓冲区中随机采样若干数据来进行训练。这么做可 以起到以下两个作用。


1.使样本满足独立假设。在 MDP中交互采样得到的数据本身不满足独立假设,因为这一时刻的状态和上一时刻的状态有关。非独立同分布的数据对训练神经网络有很大的影响,会使神经网络拟合到最近训练的数据上。采用经验回放可以打破样本之间的相关性,让其满足独立假设。


2.提高样本效率。每一个样本可以被使用多次,十分适合深度神经网络的梯度学习。


3.2 目标网络


D Q N  算法最终更新的目标是让 Q ω ( s , a ) 逼近 r + γ max ⁡ a ′ Q ω ( s ′ , a ′ ),由于 TD 误差目标本身就包含神经网络的输出,因此在更新网络参数的同时目标也在不断地改变,这非常容易造成神经网络 训练的不稳定性。为了解决这一问题, DQN 便使用了目标网络(target network) 的思想:既然训练过程中 Q 网络的不断更新会导致目标不断发生改变,不如暂时先将 TD 目标中的 Q  网络固定 住。为了实现这一思想,我们需要利用两套 Q  网络。


1.原来的训练网络 Q ω ( s , a )  ,用于计算原来的损失函数


image.png


中的 Q ω ( s , a ) 项,并且使用正常梯度下降方法来进行更新。


2.目标网络 Q ω ( s , a ),用于计算原先损失函数


image.png


中的 ( r + γ max ⁡ a ′ Q ω − ( s ′ , a ′ ) )项,其中 ω −表示目标网络中的参数。如果两套网络的参数随时保持一 致,则仍为原先不够稳定的算法。为了让更新目标更稳定,目标网络并不会每一步都更新。具体而言,目标网络使用训练网络的一套较旧的参数,训练网络 Qω (s ,a ) 在训练中的每一步都会更新, 而目标网络的参数每隔 C步才会与训练网络同步一次,即 ω ← ω 。这样做使得目标网络相对于训练网络更加稳定。


综上所述, DQN 算法的具体流程如下:


  • 用随机的网络参数 ω 初始化网络 Q ω ( s , a )


  • 复制相同的参数 ω ← ω 来初始化目标网络 Q ω ′


  • 初始化经验回放池 R


  • for 序列 e = 1 → E  do


。获取环境初始状态 s 1


。for 时间步 t = 1 → T do


  • 根据当前网络 Q ω ( s , a ) 以 ϵ-贪婪策略选择动作 a t


  • 执行动作 a t ,获得回报 r t ,环境状态变为 s t + 1


  • 将 ( s t , a t , r t , s t + 1 )存储进回放池 R 中


  • 若 R 中数据足够,从R中采样 N 个数据 { ( s i , a i , r i , s i + 1 ) } i = 1 , … , N


  • 对每个数据,用目标网络计算 y i = r i + γ max ⁡ a Q ω ( s i + 1 , a )


  • 最小化目标损失image.png ,以此更新当前网络 Q ω
  • 更新目标网络


。end for


  • end for


4. DQN 代码实践


接下来,我们就正式进入 DQN 算法的代码实践环节。我们采用的测试环境是 CartPole-v0,其状态空间相对简单,只有 4 个变量,因此网络结构的设计也相对简单:采用一层 128 个神经元的全连接并以 ReLU 作为激活函数。当遇到更复杂的诸如以图像作为输入的环境时,我们可以考虑采用深度卷积神经网络。


从 DQN 算法开始,我们将会用到rl_utils库,它包含一些专门为本书准备的函数,如绘制移动平均曲线、计算优势函数等,不同的算法可以一起使用这些函数。为了能够调用rl_utils库,请从GitHub 仓库下载rl_utils.py文件。


import random
import gym
import numpy as np
import collections
from tqdm import tqdm
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
import rl_utils


首先定义经验回放池的类,主要包括加入数据、采样数据两大函数。


class ReplayBuffer:
    ''' 经验回放池 '''
    def __init__(self, capacity):
        self.buffer = collections.deque(maxlen=capacity)  # 队列,先进先出
    def add(self, state, action, reward, next_state, done):  # 将数据加入buffer
        self.buffer.append((state, action, reward, next_state, done))
    def sample(self, batch_size):  # 从buffer中采样数据,数量为batch_size
        transitions = random.sample(self.buffer, batch_size)
        state, action, reward, next_state, done = zip(*transitions)
        return np.array(state), action, reward, np.array(next_state), done
    def size(self):  # 目前buffer中数据的数量
        return len(self.buffer)


然后定义一个只有一层隐藏层的 Q 网络。


class Qnet(torch.nn.Module):
    ''' 只有一层隐藏层的Q网络 '''
    def __init__(self, state_dim, hidden_dim, action_dim):
        super(Qnet, self).__init__()
        self.fc1 = torch.nn.Linear(state_dim, hidden_dim)
        self.fc2 = torch.nn.Linear(hidden_dim, action_dim)
    def forward(self, x):
        x = F.relu(self.fc1(x))  # 隐藏层使用ReLU激活函数
        return self.fc2(x)


有了这些基本组件之后,接来下开始实现 DQN 算法。


class DQN:
    ''' DQN算法 '''
    def __init__(self, state_dim, hidden_dim, action_dim, learning_rate, gamma,
                 epsilon, target_update, device):
        self.action_dim = action_dim
        self.q_net = Qnet(state_dim, hidden_dim,
                          self.action_dim).to(device)  # Q网络
        # 目标网络
        self.target_q_net = Qnet(state_dim, hidden_dim,
                                 self.action_dim).to(device)
        # 使用Adam优化器
        self.optimizer = torch.optim.Adam(self.q_net.parameters(),
                                          lr=learning_rate)
        self.gamma = gamma  # 折扣因子
        self.epsilon = epsilon  # epsilon-贪婪策略
        self.target_update = target_update  # 目标网络更新频率
        self.count = 0  # 计数器,记录更新次数
        self.device = device
    def take_action(self, state):  # epsilon-贪婪策略采取动作
        if np.random.random() < self.epsilon:
            action = np.random.randint(self.action_dim)
        else:
            state = torch.tensor([state], dtype=torch.float).to(self.device)
            action = self.q_net(state).argmax().item()
        return action
    def update(self, transition_dict):
        states = torch.tensor(transition_dict['states'],
                              dtype=torch.float).to(self.device)
        actions = torch.tensor(transition_dict['actions']).view(-1, 1).to(
            self.device)
        rewards = torch.tensor(transition_dict['rewards'],
                               dtype=torch.float).view(-1, 1).to(self.device)
        next_states = torch.tensor(transition_dict['next_states'],
                                   dtype=torch.float).to(self.device)
        dones = torch.tensor(transition_dict['dones'],
                             dtype=torch.float).view(-1, 1).to(self.device)
        q_values = self.q_net(states).gather(1, actions)  # Q值
        # 下个状态的最大Q值
        max_next_q_values = self.target_q_net(next_states).max(1)[0].view(
            -1, 1)
        q_targets = rewards + self.gamma * max_next_q_values * (1 - dones
                                                                )  # TD误差目标
        dqn_loss = torch.mean(F.mse_loss(q_values, q_targets))  # 均方误差损失函数
        self.optimizer.zero_grad()  # PyTorch中默认梯度会累积,这里需要显式将梯度置为0
        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())  # 更新目标网络
        self.count += 1


一切准备就绪,开始训练并查看结果。我们之后会将这一训练过程包装进rl_utils库中,方便之后要学习的算法的代码实现。


lr = 2e-3
num_episodes = 500
hidden_dim = 128
gamma = 0.98
epsilon = 0.01
target_update = 10
buffer_size = 10000
minimal_size = 500
batch_size = 64
device = torch.device("cuda") if torch.cuda.is_available() else torch.device(
    "cpu")
env_name = 'CartPole-v0'
env = gym.make(env_name)
random.seed(0)
np.random.seed(0)
env.seed(0)
torch.manual_seed(0)
replay_buffer = ReplayBuffer(buffer_size)
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.n
agent = DQN(state_dim, hidden_dim, action_dim, lr, gamma, epsilon,
            target_update, device)
return_list = []
for i in range(10):
    with tqdm(total=int(num_episodes / 10), desc='Iteration %d' % i) as pbar:
        for i_episode in range(int(num_episodes / 10)):
            episode_return = 0
            state = env.reset()
            done = False
            while not done:
                action = agent.take_action(state)
                next_state, reward, done, _ = env.step(action)
                replay_buffer.add(state, action, reward, next_state, done)
                state = next_state
                episode_return += reward
                # 当buffer数据的数量超过一定值后,才进行Q网络训练
                if replay_buffer.size() > minimal_size:
                    b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size)
                    transition_dict = {
                        'states': b_s,
                        'actions': b_a,
                        'next_states': b_ns,
                        'rewards': b_r,
                        'dones': b_d
                    }
                    agent.update(transition_dict)
            return_list.append(episode_return)
            if (i_episode + 1) % 10 == 0:
                pbar.set_postfix({
                    'episode':
                    '%d' % (num_episodes / 10 * i + i_episode + 1),
                    'return':
                    '%.3f' % np.mean(return_list[-10:])
                })
            pbar.update(1)
-----------------------------------------------------------------------------------------------------------------
Iteration 0: 100%|██████████████████████████████████████████| 50/50 [00:00<00:00, 589.55it/s, episode=50, return=9.300]
Iteration 1: 100%|█████████████████████████████████████████| 50/50 [00:00<00:00, 60.01it/s, episode=100, return=12.300]
Iteration 2: 100%|████████████████████████████████████████| 50/50 [00:04<00:00, 11.94it/s, episode=150, return=123.000]
Iteration 3: 100%|████████████████████████████████████████| 50/50 [00:15<00:00,  3.27it/s, episode=200, return=159.300]
Iteration 4: 100%|████████████████████████████████████████| 50/50 [00:16<00:00,  3.04it/s, episode=250, return=192.200]
Iteration 5: 100%|████████████████████████████████████████| 50/50 [00:15<00:00,  3.23it/s, episode=300, return=199.900]
Iteration 6: 100%|████████████████████████████████████████| 50/50 [00:15<00:00,  3.28it/s, episode=350, return=193.400]
Iteration 7: 100%|████████████████████████████████████████| 50/50 [00:16<00:00,  3.10it/s, episode=400, return=200.000]
Iteration 8: 100%|████████████████████████████████████████| 50/50 [00:15<00:00,  3.28it/s, episode=450, return=172.300]
Iteration 9: 100%|████████████████████████████████████████| 50/50 [00:15<00:00,  3.32it/s, episode=500, return=185.000]            


episodes_list = list(range(len(return_list)))
plt.plot(episodes_list, return_list)
plt.xlabel('Episodes')
plt.ylabel('Returns')
plt.title('DQN on {}'.format(env_name))
plt.show()
mv_return = rl_utils.moving_average(return_list, 9)
plt.plot(episodes_list, mv_return)
plt.xlabel('Episodes')
plt.ylabel('Returns')
plt.title('DQN on {}'.format(env_name))
plt.show()

f692818f41974627a5a2d227d69da1ed.png


可以看到,DQN 的性能在 100 个序列后很快得到提升,最终收敛到策略的最优回报值 200。我们也可以看到,在 DQN 的性能得到提升后,它会持续出现一定程度的震荡,这主要是神经网络过拟合到一些局部经验数据a r g m a x argmaxargmax后由运算带来的影响。


5. 以图像为输入的 DQN 算法


在前面章节所述的强化学习环境中,我们都使用非图像的状态作为输入(例如车杆环境中车的坐标、速度),但是在一些视频游戏中,智能体并不能直接获取这些状态信息,而只能直接获取屏幕中的图像。要让智能体和人一样玩游戏,我们需要让智能体学会以图像作为状态时的决策。我们可以利用 7.4 节的 DQN 算法,将卷积层加入其网络结构以提取图像特征,最终实现以图像为输入的强化学习。以图像为输入的 DQN 算法的代码与 7.4 节的代码的不同之处主要在于 Q 网络的结构和数据输入。DQN 网络通常会将最近的几帧图像一起作为输入,从而感知环境的动态性。接下来我们实现以图像为输入的 DQN 算法,但由于代码需要运行较长的时间,我们在此便不展示训练结果。


class ConvolutionalQnet(torch.nn.Module):
    ''' 加入卷积层的Q网络 '''
    def __init__(self, action_dim, in_channels=4):
        super(ConvolutionalQnet, self).__init__()
        self.conv1 = torch.nn.Conv2d(in_channels, 32, kernel_size=8, stride=4)
        self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=4, stride=2)
        self.conv3 = torch.nn.Conv2d(64, 64, kernel_size=3, stride=1)
        self.fc4 = torch.nn.Linear(7 * 7 * 64, 512)
        self.head = torch.nn.Linear(512, action_dim)
    def forward(self, x):
        x = x / 255
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = F.relu(self.conv3(x))
        x = F.relu(self.fc4(x))
        return self.head(x)


6. 小结


本章讲解了 DQN 算法,其主要思想是用一个神经网络来表示最优策略的函数,然后利用 Q-learning 的思想进行参数更新。为了保证训练的稳定性和高效性,DQN 算法引入了经验回放和目标网络两大模块,使得算法在实际应用时能够取得更好的效果。在 2013 年的 NIPS 深度学习研讨会上,DeepMind 公司的研究团队发表了 DQN 论文,首次展示了这一直接通过卷积神经网络接受像素输入来玩转各种雅达利(Atari)游戏的强化学习算法,由此拉开了深度强化学习的序幕。DQN 是深度强化学习的基础,掌握了该算法才算是真正进入了深度强化学习领域。


相关资源来自:伯禹学习平台-动手学强化学习


35f0c043b96a4143bb9612b6bc0f1c4b.png

目录
相关文章
|
1月前
|
机器学习/深度学习 算法 机器人
多代理强化学习综述:原理、算法与挑战
多代理强化学习是强化学习的一个子领域,专注于研究在共享环境中共存的多个学习代理的行为。每个代理都受其个体奖励驱动,采取行动以推进自身利益;在某些环境中,这些利益可能与其他代理的利益相冲突,从而产生复杂的群体动态。
176 5
|
3月前
|
机器学习/深度学习 算法 TensorFlow
深入探索强化学习与深度学习的融合:使用TensorFlow框架实现深度Q网络算法及高效调试技巧
【8月更文挑战第31天】强化学习是机器学习的重要分支,尤其在深度学习的推动下,能够解决更为复杂的问题。深度Q网络(DQN)结合了深度学习与强化学习的优势,通过神经网络逼近动作价值函数,在多种任务中表现出色。本文探讨了使用TensorFlow实现DQN算法的方法及其调试技巧。DQN通过神经网络学习不同状态下采取动作的预期回报Q(s,a),处理高维状态空间。
54 1
|
3月前
|
机器学习/深度学习 存储 算法
强化学习实战:基于 PyTorch 的环境搭建与算法实现
【8月更文第29天】强化学习是机器学习的一个重要分支,它让智能体通过与环境交互来学习策略,以最大化长期奖励。本文将介绍如何使用PyTorch实现两种经典的强化学习算法——Deep Q-Network (DQN) 和 Actor-Critic Algorithm with Asynchronous Advantage (A3C)。我们将从环境搭建开始,逐步实现算法的核心部分,并给出完整的代码示例。
250 1
|
3月前
|
测试技术 数据库
探索JSF单元测试秘籍!如何让您的应用更稳固、更高效?揭秘成功背后的测试之道!
【8月更文挑战第31天】在 JavaServer Faces(JSF)应用开发中,确保代码质量和可维护性至关重要。本文详细介绍了如何通过单元测试实现这一目标。首先,阐述了单元测试的重要性及其对应用稳定性的影响;其次,提出了提高 JSF 应用可测试性的设计建议,如避免直接访问外部资源和使用依赖注入;最后,通过一个具体的 `UserBean` 示例,展示了如何利用 JUnit 和 Mockito 框架编写有效的单元测试。通过这些方法,不仅能够确保代码质量,还能提高开发效率和降低维护成本。
52 0
|
4月前
|
机器学习/深度学习 存储 数据采集
强化学习系列:A3C算法解析
【7月更文挑战第13天】A3C算法作为一种高效且广泛应用的强化学习算法,通过结合Actor-Critic结构和异步训练的思想,实现了在复杂环境下的高效学习和优化策略的能力。其并行化的训练方式和优势函数的引入,使得A3C算法在解决大规模连续动作空间和高维状态空间的问题上表现优异。未来,随着技术的不断发展,A3C算法有望在更多领域发挥重要作用,推动强化学习技术的进一步发展。
|
5月前
|
机器学习/深度学习 分布式计算 算法
在机器学习项目中,选择算法涉及问题类型识别(如回归、分类、聚类、强化学习)
【6月更文挑战第28天】在机器学习项目中,选择算法涉及问题类型识别(如回归、分类、聚类、强化学习)、数据规模与特性(大数据可能适合分布式算法或深度学习)、性能需求(准确性、速度、可解释性)、资源限制(计算与内存)、领域知识应用以及实验验证(交叉验证、模型比较)。迭代过程包括数据探索、模型构建、评估和优化,结合业务需求进行决策。
58 0
|
6月前
|
机器学习/深度学习 算法
算法人生(2):从“强化学习”看如何“活在当下”
本文探讨了强化学习的原理及其在个人生活中的启示。强化学习强调智能体在动态环境中通过与环境交互学习最优策略,不断迭代优化。这种思想类似于“活在当下”的哲学,要求人们专注于当前状态和决策,不过分依赖历史经验或担忧未来。活在当下意味着全情投入每一刻,不被过去或未来牵绊。通过减少执着,提高觉察力和静心练习,我们可以更好地活在当下,同时兼顾历史经验和未来规划。文章建议实践静心、时间管理和接纳每个瞬间,以实现更低焦虑、更高生活质量的生活艺术。
|
27天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
12天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
13天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。