【机器学习】【遗传算法】【项目实战】药品分拣的优化策略【附Python源码】

news2024/10/5 22:25:05

仅供学习、参考使用

一、遗传算法简介

遗传算法(Genetic Algorithm, GA)是机器学习领域中常见的一类算法,其基本思想可以用下述流程图简要表示:

(图参考论文:Optimization of Worker Scheduling at Logistics
Depots Using GeneticAlgorithms and Simulated
Annealing)

在这里插入图片描述

一种常见的遗传算法变例是有偏随机密匙遗传算法 (BRKGA: Biased Random Key Genetic Algorithm) ,参考论文:A BIASED RANDOM-KEY GENETIC ALGORITHM WITH VARIABLE MUTANTS TO
SOLVE A VEHICLE ROUTING PROBLEM,算法流程大致如下:
(图参考博客:Pymoo学习 (11):有偏随机密匙遗传算法 (BRKGA: Biased Random Key Genetic Algorithm) 的使用)

在这里插入图片描述

二、项目源码(待进一步完善)

1、导入相关库

import csv
import random
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt

2、药品统计

# 统计zone_id=2110的药品
def screen_goods_id(tote_data, zone):
    zone_goods_id_lists = []
    for i in range(len(tote_data)):
        zone_id = tote_data['区段ID'][i]
        goods_id = tote_data['产品编号'][i]
        if zone_id == zone:
            zone_goods_id_lists.append(goods_id)
    zone_goods_id_lists = list(set(zone_goods_id_lists))
    return zone_goods_id_lists

3、货位统计

# 统计zone_id=2110的货位
def generate_locations():
    index_id_0 = [2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181]
    index_id_1 = [1, 2, 3, 4, 5, 6, 7, 8]
    index_id_2 = [21, 22, 23, 24, 25, 31, 32, 33, 34, 35, 41, 42, 43, 44, 45]
    location_id_data = [f"{aa:04d}{bb:02d}{cc:02d}1" for aa in index_id_0 for bb in index_id_1 for cc in index_id_2]
    return location_id_data

4、缺失货位统计

# 统计zone_id=2110的缺失货位
def del_locations():
    index_id_0 = [217408, 217507, 217708, 217807, 218008, 218107]
    index_id_1 = [22, 23, 24, 25, 32, 33, 34, 35, 42, 43, 44, 45]
    del_loc_data = [f"{aa:06d}{bb:02d}1" for aa in index_id_0 for bb in index_id_1]
    return del_loc_data

5、生成可使用货位

# 去除缺失货位,生成最终的可使用货位
def screen_location_id():
    location_id_data = generate_locations()
    del_loc_data = del_locations()
    location_id_lists = [loc_id for loc_id in location_id_data if loc_id not in del_loc_data]
    return location_id_lists

6、个体(单个基因型)生成

# 生成一个个体
def pop_one_combined(list_1, list_2):  # list1的长度不能大于list2
    goods_ids_copy = list_1[:]
    location_ids_copy = list_2[:]
    combined_list = []
    for _ in range(len(list_1)):
        element = random.choice(location_ids_copy)
        location_ids_copy.remove(element)
        combined_list.append(element)
    return combined_list

生成测试:大小为6的一维数组,生成50个个体(种群类似):

list1 = [1, 2, 3, 4, 5, 6]
list2 = [1, 2, 3, 4, 5, 6]

# 个体生成测试(批量生成)

for i in range(50):
    print(pop_one_combined(list1, list2))

在这里插入图片描述
7、种群(基因池)生成

# 生成种群
def generate_pop_list(POP_SIZE, zone_goods_id_data, zone_location_id_data):
    pop_list = []
    for _ in range(POP_SIZE):
        pop_individuality = pop_one_combined(zone_goods_id_data, zone_location_id_data)
        pop_list.append(pop_individuality)
    return pop_list

生成测试:

# 种群生成测试(样本量50)
print(generate_pop_list(50, list1, list2))

在这里插入图片描述
8、劳累值(特征系数)计算公式

# 拣选劳累值计算公式
def pick_distance_formula(location_id, shelves_num):
    if location_id[-2] == '4':  # 第4层(最高层)
        distance = 10 * (int(location_id[0:4]) - 2173) + (shelves_num - 1) * 10 + int(location_id[-3]) + 3
    else:  # 第1~3层
        distance = 10 * (int(location_id[0:4]) - 2173) + (shelves_num - 1) * 10 + int(location_id[-3])
    return distance

9、一组数据的劳累值计算

# 拣选劳累值计算(一组)
def pick_distance_value(location_id):
    distance = 0
    shelves_num = int(location_id[4:6])
    group_1 = [1, 3, 5, 7]
    group_2 = [2, 4, 6, 8]
    if shelves_num in group_1:
        shelves_num = shelves_num // 2 + 1
    elif shelves_num in group_2:
        shelves_num = shelves_num // 2
    distance = pick_distance_formula(location_id, shelves_num)
    return distance

10、选择优势个体进入下一代

# 选择优胜个体
def select(pop_list, CROSS_RATE, POP_SIZE):
    index = int(CROSS_RATE * POP_SIZE)  # 一轮筛选后的样本数量
    return pop_list[0:index]  # 返回前xxx个优胜个体

11、遗传变异机制

# 遗传变异
def mutation(MUTA_RATE, child, zone_goods_id_data, zone_location_id_data):
    if np.random.rand() < MUTA_RATE:
        mutation_list = [loc_id for loc_id in zone_location_id_data if loc_id not in child]
        num = np.random.randint(1, int(len(zone_goods_id_data) * MUTA_RATE))
        for _ in range(num):
            index = np.random.randint(0, len(zone_goods_id_data))
            mutation_list.append(child[index])
            loc_id = random.choice(mutation_list)
            child[index] = loc_id
    return child

12、子代中0值的替换

# (子代)0值的替换
def obx_count_run(child, parent):
    for parent_elemental in parent:
        if parent_elemental not in child:
            for i in range(len(child)):
                if child[i] == 0:
                    child[i] = parent_elemental
                    break
    return child

13、基于顺序的交叉方式(Order-Based Crossover, OBX)

# 遗传交叉(交叉算子:基于顺序的交叉(Order-Based Crossover,OBX))
def crossmuta(pop_list, POP_SIZE, MUTA_RATE, zone_goods_id_data, zone_location_id_data):
    pop_new = []
    for i in range(len(pop_list)):
        pop_new.append(pop_list[i][1:])
    while len(pop_new) < POP_SIZE:
        parent_1 = random.choice(pop_list)[1:]
        parent_2 = random.choice(pop_list)[1:]
        while parent_1 == parent_2:
            parent_2 = random.choice(pop_list)[1:]
        child_1 = [0 for _ in range(len(zone_goods_id_data))]
        child_2 = [0 for _ in range(len(zone_goods_id_data))]
        for j in range(len(zone_goods_id_data)):
            genetic_whether = np.random.choice([0, 1])
            if genetic_whether == 1:
                child_1[j] = parent_1[j]
                child_2[j] = parent_2[j]
        if (child_1 == parent_1) or (child_2 == parent_2):
            continue
        child_1 = obx_count_run(child_1, parent_2)
        child_1 = mutation(MUTA_RATE, child_1, zone_goods_id_data, zone_location_id_data)
        child_2 = obx_count_run(child_2, parent_1)
        child_2 = mutation(MUTA_RATE, child_2, zone_goods_id_data, zone_location_id_data)
        pop_new.append(child_1)
        pop_new.append(child_2)
    return pop_new

14、损失曲线图绘制

# 每轮总拣选劳累值绘制曲线图
def loss_chart(data):
    y_values = data
    x_values = list(range(len(y_values)))
    plt.plot(x_values, y_values)
    plt.title("zone_2110_pick_distance_loss")
    plt.xlabel("Iterations")  # 迭代次数
    plt.ylabel("zone_2110_pick_distance")  # 距离
    plt.grid()
    plt.savefig('./JS_zone_2110_pick_distance_loss.png')
    plt.show()

15、结果合成

# 最终结果合成
def goods_location_data_consolidation(zone_goods_id_data, zone_goods_location_id_data):
    goods_location_data = []
    for i in range(len(zone_goods_id_data)):
        goods_location_data.append([zone_goods_id_data[i], zone_goods_location_id_data[i]])
    return goods_location_data

主函数及运行:

def main():
    list1 = [1, 2, 3, 4, 5, 6]
    list2 = [1, 2, 3, 4, 5, 6]

    # 个体生成测试(批量生成)

    for i in range(50):
        print(pop_one_combined(list1, list2))

    # 种群生成测试(样本量50)
    print(generate_pop_list(50, list1, list2))

    print("Genetic algorithm run start")
    print(f"start_time --> {datetime.now()}")
    zone_2110_pick_distance = []
    tote_goods_data_2403 = pd.read_csv('./tote_goods_data_2024_03.csv')  # 读取数据集
    POP_SIZE = 20  # 种群大小
    CROSS_RATE = 0.9  # 交叉率
    MUTA_RATE = 0.05  # 变异率
    Iterations = 10  # 迭代次数
    zone_2110_goods_id_lists = screen_goods_id(tote_goods_data_2403, 2110)
    zone_2110_location_id_lists = screen_location_id()
    POP = generate_pop_list(POP_SIZE, zone_2110_goods_id_lists, zone_2110_location_id_lists)
    for i in range(Iterations):
        POP = getfitness(POP, 2110, tote_goods_data_2403, zone_2110_goods_id_lists)
        POP = select(POP, CROSS_RATE, POP_SIZE)
        zone_2110_pick_distance.append(POP[0][0])
        POP = crossmuta(POP, POP_SIZE, MUTA_RATE, zone_2110_goods_id_lists, zone_2110_location_id_lists)
    loss_chart(zone_2110_pick_distance)

    Updated_goods_location_data = goods_location_data_consolidation(zone_2110_goods_id_lists, POP[0])
    with open('./zone_2110_goods_location_data.csv', 'w', newline='') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(['goods_id', 'location_id'])
        for row in Updated_goods_location_data:
            writer.writerow(row)

    print(f"end_time --> {datetime.now()}")
    print("Genetic algorithm run end")


if __name__ == "__main__":
    main()

三、算法测试

1、pop_size=20, iterations=10
cross_rate=0.5, muta_rate=0.05:
在这里插入图片描述
交叉率不变,增加变异率到0.1:

在这里插入图片描述

交叉率不变,增加变异率到0.2:

在这里插入图片描述

变异率不变,增加交叉率到0.9:

在这里插入图片描述

2、在另一个数据集上进行测试

采用初始参数设定:
在这里插入图片描述

交叉率提高至0.9:
在这里插入图片描述

四、算法优化

GA(遗传)算法优化可行性分析

一、优化算法核心步骤参数

GA(Genetic Algorithm,遗传算法)的主要流程可以用下图进行简要描述:

在初始化阶段,需要确定imax(最大迭代次数)的值用于主循环的迭代。除这个值外,在算法的“交叉”步骤中,需要确定交叉方法(常用的交叉方法包括单点交叉、两点交叉、多点交叉、部分匹配交叉、均匀交叉、顺序交叉、基于位置的交叉、基于顺序的交叉、循环交叉、子路径交换交叉等),并指定参数cross_rate(交叉率)的值;在“变异”步骤中,需要指定参数muta_rate(变异率)的值;在“适应度计算”步骤中,需要自定义适应度(fitness)计算公式。故而可以进行优化的参数包括:
(1)最大迭代次数;
(2)交叉方法;(待验证)
(3)交叉率;
(4)变异率;(结论:提高变异率可以显著提高损失函数的收敛速度)
(5)适应度计算公式(涉及到按比例缩放的问题)。可能的策略:使用二次或者高次函数?如何提高损失函数的收敛速度?

二、采用GA的常见变式

上述流程图为GA的最基本的形式(基础GA),常见的优化变式包括:
(1)GA+SA——遗传算法结合模拟退火(Simulated Annealing)算法;
见论文:《Optimization of Worker Scheduling at Logistics
Depots Using Genetic Algorithms and Simulated
Annealing》
(2)AQDE(Adaptive Quantum Differential Evolution)算法(适应性量子差分进化算法);
见论文:《Z. Sun, Z. Tian, X. Xie, Z. Sun, X. Zhang, and G. Gong, “An metacognitive based logistics human resource modeling and optimal
scheduling,”》
(3)BRKGA(Biased Random-Key Genetic Algorithm)算法(有偏随机密钥遗传算法);
见论文:《A Biased Random-Key Genetic Algorithm With Variable Mutants To Solve a Vehicle Routing Problem》

三、结合深度学习或者强化学习

todo

四、其他可行方法

其他可行方法主要包括:
(1)向量化(vectorization);
(2)多线程(multithreading);
(3)并行计算(multiprocessing);
(4)带缓存的多级计算(cached computation)。

并行计算方面,可以使用Python中的joblib库:

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

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

相关文章

Linux下软件安装

提示&#xff1a;制作不易&#xff0c;可以点个关注和收藏哦。 前言 介绍 Ubuntu 下软件安装的几种方式&#xff0c;及 apt&#xff0c;dpkg 工具的使用。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考. 一、先体验一下 比如我们想安装一个软件&…

DDMA信号处理以及数据处理的流程---随机目标生成

Hello&#xff0c;大家好&#xff0c;我是Xiaojie&#xff0c;好久不见&#xff0c;欢迎大家能够和Xiaojie一起学习毫米波雷达知识&#xff0c;Xiaojie准备连载一个系列的文章—DDMA信号处理以及数据处理的流程&#xff0c;本系列文章将从目标生成、信号仿真、测距、测速、cfar…

Unity Standard shader 修改(增加本地坐标裁剪)

本想随便找一个裁剪的shader&#xff0c;可无奈的是没找到一个shader符合要求&#xff0c;美术制作的场景都是用的都标准的着色器他们不在乎你的功能逻辑需求&#xff0c;他们只关心场景的表现&#xff0c;那又找不到和unity标准着色器表现一样的shader 1.通过贴图的透明通道做…

设计软件有哪些?效果工具篇(3),渲染100邀请码1a12

这次我们再介绍一批渲染效果和后期处理的工具。 1、ColorCorrect ColorCorrect是一种图像处理技术&#xff0c;用于调整图像的色彩和对比度&#xff0c;使其更加自然和平衡。通过ColorCorrect&#xff0c;用户可以调整图像的色调、亮度、饱和度等参数&#xff0c;以达到理想的效…

网络资源模板--基于Android Studio 实现的音乐播放器

一、项目源码获取(非开源) 关注公众号&#xff1a;《编程乐学》 后台回复&#xff1a;24060801 二、项目测试视频 网络资源模板--基于Android Studio 音乐播放器 三、项目简介 四、项目测试环境 五、项目详情设计图 1.登录注册页面介绍 <?xml version"1.0" enco…

【ai】pycharm远程ssh开发

方式1: gateway的方式是远程放一个pycharm 专业版,经常下载失败 方式2: 类似vs,源码本地,同步到远程进行运行。 参考大神的分享: Pycharm远程连接服务器(2023-11-9) Pycharm远程连接服务器(windows下远程修改服务器代码)[通俗易懂] cpolar 建议同时内网穿透 选 远程开…

你还在纠结U盘怎么选吗?小白带你来看

前言 2024年的618活动已经开始了&#xff0c;这个活动买电子产品着实是比其他时间要便宜很多。 前几天小白的一个好朋友问我&#xff1a;U盘该怎么选&#xff1f; 呃&#xff0c;本来是想写“老朋友”的&#xff0c;结果她愣是要我改成“好朋友”。 行吧&#xff0c;那就好朋…

牛客NC18 顺时针旋转矩阵【中等 数学 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/2e95333fbdd4451395066957e24909cc https://www.lintcode.com/problem/161/ 思路 Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#…

Transformer 动画讲解:单头注意力和多头注意力

暑期实习基本结束了&#xff0c;校招即将开启。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。提前准备才是完全之策。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c…

用 Python 撸一个 Web 服务器-第4章:动态渲染数据

上一章中为了尽快让 Todo List 程序跑起来&#xff0c;并没有完全按照 MVC 模式编写程序。这一章就让我们一起实现一个完整的 MVC 模式 Todo List 程序首页。 使用模型操作数据 我们来分析下请求 Todo List 程序首页时&#xff0c;模型层需要做哪些事情。当一个请求到达首页视…

区间预测 | Matlab实现LSTM-ABKDE长短期记忆神经网络自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现LSTM-ABKDE长短期记忆神经网络自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现LSTM-ABKDE长短期记忆神经网络自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现LSTM-ABKDE长…

Web学习_SQL注入_联合查询注入

UNION 操作符用于合并两个或多个 SELECT 语句的结果集&#xff0c; UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句 中的列名&#xff0c;并且UNION 内部的 SELECT 语句必须拥有相同数量的 列。 联合查询注入就是利用union操作符&#xff0c;将攻击者希望查询的语句…

【QT5】<总览五> QT多线程、TCP/UDP

文章目录 前言 一、QThread多线程 二、QT中的TCP编程 1. TCP简介 2. 服务端程序编写 3. 客户端程序编写 4. 服务端与客户端测试 三、QT中的UDP编程 1. UDP简介 2. UDP单播与广播程序 前言 承接【QT5】&#xff1c;总览四&#xff1e; QT常见绘图、图表及动画。若存在…

[Vue-常见错误]浏览器显示Uncaught runtime errors

文章目录 错误描述正确写法具体如下 错误描述 当前端代码发生错误时&#xff0c;浏览器中出现以下错误提示。 正确写法 显然这不是我们所期望的&#xff0c;在vue.config.js中配置如下设置关闭Uncaught runtime errors显示 devServer: {client: {overlay: false}具体如下 …

Java核心: 类加载器

这一节我们来学习Java的类加载器&#xff0c;以及常用的类加载器实现URLClassLoader。 1. Java类加载器 类加载器用于将字节码读取并创建Class对象。我们知道JVM本身是用C写的&#xff0c;一开始执行的时候由C程序来加载并引导字节码的运行&#xff0c;这些由C编写的加载字节…

图神经网络(GNN)的原理及应用

什么是图神经网络 &#xff08;GNN&#xff09;&#xff1f; 图神经网络 &#xff08;GNN&#xff09; 是一种神经网络架构和深度学习方法&#xff0c;可以帮助用户分析图&#xff0c;使他们能够根据图的节点和边描述的数据进行预测。 图形表示数据点&#xff08;也称为节点&…

ENSP校园网设计实验

前言 哈喽&#xff0c;我是ICT大龙。本次更新了使用ENSP仿真软件设计校园网实验。时间比较着急&#xff0c;可能会有错误&#xff0c;欢迎大家指出。 获取本次工程文件方式在文章结束部分。 拓扑设计 拓扑介绍---A校区 如图&#xff0c;XYZ大学校园网设计分为3部分&#xff0…

硬盘坏了数据能恢复吗 硬盘数据恢复一般多少钱

在数字化时代&#xff0c;我们的生活和工作离不开电脑和硬盘。然而&#xff0c;硬盘故障是一个常见的问题&#xff0c;可能会导致我们的数据丢失。当我们的硬盘坏了&#xff0c;还能恢复丢失的数据吗&#xff1f;今天我们就一起来探讨关于硬盘坏了数据能恢复吗&#xff0c;硬盘…

请求 响应

在web的前后端分离开发过程中&#xff0c;前端发送请求给后端&#xff0c;后端接收请求&#xff0c;响应数据给前端 请求 前端发送数据进行请求 简单参数 原始方式 在原始的web程序中&#xff0c;获取请求参数&#xff0c;需要通过HttpServletRequest 对象手动获取。 代码…

如何在本地和远程删除 Git 分支

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;目前是武汉城市开发者社区主理人 擅长.net、C、python开发&#xff0c; 如果遇…