遥感之特征选择-禁忌搜索算法

各类智能优化算法其主要区别在于算法的运行规则不同,比如常用的遗传算法,其规则就是变异,交叉和选择等,各种不同的变体大多是在框架内的实现细节不同,而本文中的禁忌算法也是如此,其算法框架如下进行介绍。
智能优化算法和其他算法的最大不同在于,其没有太高深的数学理论和公式,主要是基于一种设定规则运行,其规则的设置背后有优美的哲学味道,所以它能有效解决一些问题,而同时不少人对比表示怀疑的态度,只有当真正的跑一遍代码,看看效果,才能对背后的思想有所领悟。
一言以蔽之,智能优化算法,是简洁,优美和有效的。

禁忌搜索算法(Tabu Search,TS)是一种基于局部搜索的启发式算法,它通过记录搜索历史和禁止重复访问已访问过的局部最优解,来跳出局部最优,从而找到全局最优解。它模仿了人类行为中的“记忆”和“遗忘”机制,是一种简单而有效的全局优化方法。

禁忌搜索算法的原理

禁忌搜索算法的核心思想是“禁止重复”和“记忆”。它通过以下方式实现:
禁忌表:记录最近访问过的局部最优解或其状态,以及相应的禁忌长度。
搜索方向:在当前解的邻域中搜索候选解,并根据评价函数选择最好的解。
禁忌更新:将当前解或其状态添加到禁忌表中,并设置禁忌长度。
禁忌解除:当候选解被禁忌时,根据特赦规则决定是否允许访问该解。
搜索终止:达到最大迭代次数或找到全局最优解时,算法终止。
禁忌搜索算法的步骤
初始化:设置初始解,并计算其目标函数值。
搜索:在当前解的邻域中搜索候选解,并根据评价函数选择最好的解。
更新禁忌表:将当前解或其状态添加到禁忌表中,并设置禁忌长度。
禁忌解除:如果候选解被禁忌,则根据特赦规则决定是否允许访问该解。
搜索终止:达到最大迭代次数或找到全局最优解时,算法终止。
其算法流程图如下所示;
在这里插入图片描述

禁忌搜索算法的优缺点

优点:

  • 跳出局部最优:通过禁忌表和特赦规则,能够有效跳出局部最优,寻找全局最优解。
  • 全局搜索能力:具有全局搜索能力,能够搜索整个解空间。
  • 易于实现:算法结构简单,易于实现。
  • 参数选择灵活:禁忌表大小、禁忌长度、特赦规则等参数可以根据问题进行调整。
    缺点:
  • 计算复杂度:禁忌表需要存储搜索历史,可能会增加计算复杂度。
  • 参数选择困难:参数选择对算法性能影响较大,需要根据问题进行调整。
  • 无法保证找到全局最优解:虽然能够有效跳出局部最优,但无法保证找到全局最优解。

代码

在遥感高光谱领域中会经常遇到波段选择的问题,基于此,利用禁忌搜索算法完成特征选择的案例,代码可以直接运行。
代码中对于上述提到的步骤的每个环节只是用简单的方式进行实现,比如初始化这步,在实际中通常对高光谱波段之间的相关性进行研究,划分不同的,在每个块中选择一些波段作为初始化的解,以及对于候选解是如何选择的,是否需要进一步根据经验设定规则等,在实际中需要在此代码基础上进一步完善即可。

import numpy as np
import random
class TabuSearchFeatureSelection:
    '''
    代码说明:
    1. `TabuSearchFeatureSelection` 类定义了禁忌搜索算法,包括初始化、适应度函数、获取邻居、更新禁忌表、选择最佳邻居和选择特征等方法。
    2. `initialize_population` 方法初始化当前特征集为所有特征。
    3. `get_neighbors` 方法获取当前特征的邻居,包括删除一个特征和添加一个特征两种情况。
    4. `update_tabu_list` 方法更新禁忌表,将特征集添加到禁忌表。
    5. `select_best_neighbor` 方法从邻居中选择最佳特征集,优先选择不在禁忌表中的特征集,并选择适应度值最高的特征集。
    6. `select_features` 方法进行特征选择,循环迭代更新当前特征集,直到没有更好的邻居或达到最大迭代次数。
    7. `best_features` 和 `best_score` 分别存储最佳特征集和最佳得分。
    '''
    def __init__(self, n_iterations, tabu_size, feature_set, data, labels, model):
        """
        禁忌搜索算法初始化
        :param n_iterations: 迭代次数
        :param tabu_size: 禁忌表大小
        :param feature_set: 特征集
        :param data: 数据集
        :param labels: 标签
        :param model: 机器学习模型
        """
        self.n_iterations = n_iterations
        self.tabu_size = tabu_size
        self.feature_set = feature_set
        self.data = data
        self.labels = labels
        self.model = model
        self.best_score = float('-inf')
        self.best_features = None
        self.tabu_list = []
    def fitness(self, features):
        """
        适应度函数,计算模型在当前特征集上的性能
        :param features: 当前特征集
        :return: 适应度值
        """
        X_train = self.data[:, features]
        clf = self.model.fit(X_train, self.labels)
        score = clf.score(X_train, self.labels)
        return score
    def get_neighbors(self, features):
        """
        获取当前特征的邻居
        :param features: 当前特征集
        :return: 邻居特征集列表
        """
        neighbors = []
        for i in range(len(self.feature_set)):
            if i in features:
                new_features = np.array(features)
                new_features = np.delete(new_features, np.where(new_features == i)[0][0])
                neighbors.append(new_features)
            else:
                new_features = np.array(features)
                new_features = np.append(new_features, i)
                neighbors.append(new_features)
        return neighbors
    def update_tabu_list(self, features):
        """
        更新禁忌表
        """
        # 将特征集添加到禁忌表
        if len(self.tabu_list) >= self.tabu_size:
            self.tabu_list.pop(0)
        self.tabu_list.append(tuple(features))
    def select_best_neighbor(self, neighbors):
        """
        从邻居中选择最佳特征集
        :param neighbors: 邻居特征集列表
        :return: 最佳特征集
        """
        best_score = float('-inf')
        best_features = None
        for neighbor in neighbors:
            if tuple(neighbor) in self.tabu_list:
                continue
            score = self.fitness(neighbor)
            if score > best_score:
                best_score = score
                best_features = neighbor
        return best_features
    def select_features(self):
        """
        选择特征
        """
        # 初始化当前特征集
        current_features = np.arange(self.data.shape[1])
        for _ in range(self.n_iterations):
            # 获取邻居
            neighbors = self.get_neighbors(current_features)
            # 选择最佳邻居
            best_neighbor = self.select_best_neighbor(neighbors)
            # 如果没有更好的邻居,则终止搜索
            if best_neighbor is None:
                break
            # 更新当前特征集
            current_features = best_neighbor
            # 更新禁忌表
            self.update_tabu_list(current_features)
            # 更新最佳解
            if self.fitness(current_features) > self.best_score:
                self.best_score = self.fitness(current_features)
                self.best_features = current_features
        return self.best_features, self.best_score
# 示例用法
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
# 加载数据集
data = load_iris().data
labels = load_iris().target
# 初始化模型
model = LogisticRegression(solver='newton-cg')
# 初始化禁忌搜索算法
tabu_search = TabuSearchFeatureSelection(n_iterations=2, tabu_size=1, feature_set=np.arange(data.shape[1]), data=data, labels=labels, model=model)
# 选择特征
best_features, best_score = tabu_search.select_features()
print("最佳特征:", best_features)
print("最佳得分:", best_score)

总结

此类算法,了解其规则即可,在规则之内可以扩展展开。

欢迎关注专栏:智能优化算法专栏

欢迎点赞,收藏,关注,支持小生,打造一个好的遥感领域知识分享专栏。
同时欢迎私信咨询讨论学习,咨询讨论的方向不限于:地物分类/语义分割(如水体,云,建筑物,耕地,冬小麦等各种地物类型的提取),变化检测,夜光遥感数据处理,目标检测,图像处理(几何矫正,辐射矫正(大气校正),图像去噪等),遥感时空融合,定量遥感(土壤盐渍化/水质参数反演/气溶胶反演/森林参数(生物量,植被覆盖度,植被生产力等)/地表温度/地表反射率等反演)以及高光谱数据处理等领域以及深度学习,机器学习等技术算法讨论,以及相关实验指导/论文指导等多方面。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【一刷《剑指Offer》】面试题 31:连续子数组的最大和

牛客对应题目链接:连续子数组最大和_牛客题霸_牛客网 (nowcoder.com) 力扣对应题目链接:53. 最大子数组和 - 力扣(LeetCode) 核心考点 :简单动归问题。 一、《剑指Offer》对应内容 二、分析题目 1、贪心 从前往后迭…

VRTK4教程 一:资源导入、Unity设置、连接头盔

文章目录 VRTK4的分包导入VRTK4的资源包unity设置连接头盔 VRTK4的分包 vrtk4的资源包和旧版不同,采用了分包导入的思想,我们要用什么功能,就导入什么包,可以有效减小程序体积 如下图,已经导入的vrtk包会显示在Packag…

C语言—深入理解指针(5)

1. sizeof 和 strlen 的对比 1.1 sizeof 在学习操作符的时候,我们学习了 sizeof,sizeof 是计算变量所占内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。 sizeof 只…

MicroBlaze 处理器参考指南

概述 本章包含MicroBlaze功能的概述和详细信息MicroBlaze架构包括Big-Endian或Little-Endian位反转格式,32位或64位通用寄存器,虚拟内存管理,缓存软件支持,和AXI4-Stream接口 简介 MicroBlaze嵌入式处理器软核是一个精简指令集…

调查问卷和考试系统SurveyKing

什么是 SurveyKing ? SurveyKing 是功能更强大的调查问卷、考试系统,很多功能体验超过问卷网、问卷星。支持在线考试/调查问卷/公开查询/题库刷题/投票。 软件特性 🥇 支持 20 多种题型,如填空、选择、下拉、级联、矩阵、分页、签…

CANDela studio的DTC

可以在文件——属性里面选择支持的规范 想要添加DTC,首先要在Diagnostic Trouble Codes里面的Available DTCs Fault Memory里面进行添加,不过这只是添加在池子里面,并不能使用。 添加完了之后在fault memory里面copy进来, 这样就能…

VRRP

文章目录 VRRP基本原理技术背景VRRP作用VRRP概述VRRP名词解释VRRP路由器VRRP组虚拟路由器虚拟IP地址、MAC地址Master、Backup路由器 VRRP状态机Master/ Backup 路由器Master路由器:Backup路由器: VRRP的工作过程 VRRP基础配置![image.png](https://img-blog.csdnimg.cn/img_con…

【逻辑回归】Logistic Regression逻辑回归模型学习笔记

文章目录 序言1. 线性回归2. 逻辑回归2.1 引入逻辑回归的原因2.2 逻辑回归2.3 逻辑回归的应用 3. 逻辑函数3.1 sigmoid函数3.2 sigmoid函数的性质3.3 决策边界3.4 对数几率 4. 损失函数4.1 为什么说逻辑回归时概率类模型4.2 为什么要进行极大似然估计4.3 利用MLE如何推导出损失…

MySQL嵌套,别名,分组查询

有以下三张表:分别是课程表c,有课程号cno,课程名cname,课程类别cpro等 学生信息表s,学号sno,姓名sname,性别ssex,年龄sage,班级sclass,籍贯jg 成绩表sc&#…

C++STL---list知识汇总

前言 学习完list,我们会对STL中的迭代器有进一步的认识。list底层有很多经典的东西,尤其是他的迭代器。而list的结构是一个带头双向循环链表。 list没有reserve和resize,因为它底层不是连续的空间,它是用时随时申请,…

【QT】父子按钮同时响应点击事件

QPushButton如何响应点击事件 QPushButton::event(QEvent *e) 。可以看到在QPushButton中的event函数中并没有鼠标点击相关的操作,那么我们去QAbstractButton::event中寻找 damn it!。依然没有那我们去QWidget::event中寻找 damn it! 只有mousePressEvent mouseR…

c++学生管理系统

想要实现的功能 1,可以增加学生的信息,包括(姓名,学号,c成绩,高数成绩,英语成绩) 2,可以删除学生信息 3,修改学生信息 4,显示所有学生信息 5&#xff0c…

python中利用cartopy库绘制SST图像

1. Cartopy简介 Cartopy 是一个开源的 Python 库,用于绘制地图和地理数据分析。它结合了 matplotlib 的绘图功能和 shapely、pyproj 等库的地理空间数据处理能力,为用户提供了在地图上可视化数据的强大工具。 以下是 Cartopy 的一些主要特点和功能&#…

微信公众号开发(问题1):订阅号不能定时发私信/私信

微信公众号开发时,因为个人使用,申请的是订阅号,本来是想出了自动回复,再加一个定时消息的功能,尝试利用flask里的scheduler添加定时任务,但是执行之后不能收到消息,通过再次查看订阅号的功能&a…

stm32mp157为什么要把相同的tf-A trust烧录emmc的boot1和boot2?

在使用该处理器时,为什么要将相同的Trusted Firmware-A (TF-A)烧录到eMMC的Boot1和Boot2区域呢? 这么做的主要原因包括: 冗余性和可靠性: 将相同的TF-A烧录到两个不同的引导区域(Boot1和Boot2)可以增加系…

LeetCode 算法:找到字符串中所有字母异位词c++

原题链接🔗:找到字符串中所有字母异位词 难度:中等⭐️⭐️ 题目 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符…

Jenkins流水线pipeline--基于上一章的工作流程

1流水线部署 1.流水线文本名Jenkinsfile,将流水线放入gitlab远程仓库代码里面 2pipeline脚本 Jenkinsfile文件内容 pipeline {agent anyenvironment {key"value"}stages {stage("拉取git仓库代码") {steps {deleteDir()checkout scmGit(branches: [[nam…

人工智能与【肿瘤免疫微环境】结合,探索免疫治疗的新方向|24年6月·顶刊速递·06-02

罗小罗同学说 24-06-02|文献速递 今天分享的文章,主题是——人工智能&肿瘤免疫微环境。解释一下这张图,左列是文献标题,右侧是发表的年月,放心,都是顶刊,不然我也不会选的。 PS&#xff1a…

大数据测试/ETL开发,如何造测试数据

相信很多的小伙伴,有些是大数据测试岗位,有些是ETL开发,都面临着如何要造数据的情况。 1,造数背景 【大数据测试岗位】,比较出名的就是宁波银行,如果你在宁波银行做大数据开发,对着需求开发完…

Java——常见进制

在计算机领域有四种比较常见的进制,分别是二进制、八进制、十进制和十六进制。 一、二进制(Binary) 二进制(Binary)是一种基数为2的数值系统,仅使用两个符号:0和1。所以它的进位规则就是逢二进…