贪心算法应用:装箱问题(BFD算法)详解

article/2025/7/5 10:00:37

在这里插入图片描述

贪心算法应用:装箱问题(BFD算法)详解

1. 装箱问题与BFD算法概述

1.1 装箱问题定义

装箱问题(Bin Packing Problem)是组合优化中的经典问题,其定义为:

  • 给定n个物品,每个物品有大小wᵢ (0 < wᵢ ≤ C)
  • 无限数量的箱子,每个箱子容量为C
  • 目标:用最少数量的箱子装下所有物品

1.2 BFD算法简介

最佳适应递减算法(Best Fit Decreasing, BFD)是解决装箱问题的高效启发式算法:

  1. 先将所有物品按大小降序排序
  2. 然后对每个物品,将其放入能容纳它且剩余空间最小的箱子
  3. 若无合适箱子,则开启新箱子

与FFD的区别:

  • FFD选择第一个能装下物品的箱子
  • BFD选择最适合(剩余空间最小)的箱子

2. BFD算法详细解析

2.1 算法思想

BFD算法的核心思想是:

  • 排序阶段:大物品优先处理,减少碎片空间
  • 放置阶段:每次选择最合适的箱子,提高空间利用率

2.2 算法步骤

  1. 输入:物品列表items,箱子容量C
  2. 排序:将items按非递增顺序排序
  3. 初始化:创建空箱子列表bins
  4. 分配物品
    • 对于每个物品item:
      • 遍历所有箱子,找到满足条件且剩余空间最小的箱子
      • 若找到,放入该箱子
      • 若未找到,创建新箱子并放入
  5. 输出:使用的箱子列表

2.3 伪代码表示

function BFD(items, C):sortedItems = sortDescending(items)bins = []for item in sortedItems:bestBin = nullminSpace = C + 1  // 初始化为大于最大可能值for bin in bins:space = C - bin.currentWeightif space >= item and space < minSpace:bestBin = binminSpace = spaceif bestBin != null:bestBin.add(item)else:newBin = new Bin(C)newBin.add(item)bins.add(newBin)return bins

3. Java实现BFD算法

3.1 基础实现

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class BinPackingBFD {public static void main(String[] args) {List<Integer> items = List.of(4, 8, 5, 1, 2, 3, 6, 7, 9, 4);int binCapacity = 10;List<List<Integer>> bins = bestFitDecreasing(items, binCapacity);printBins(bins);}public static List<List<Integer>> bestFitDecreasing(List<Integer> items, int binCapacity) {// 复制并排序物品列表List<Integer> sortedItems = new ArrayList<>(items);Collections.sort(sortedItems, Collections.reverseOrder());List<List<Integer>> bins = new ArrayList<>();List<Integer> binCapacities = new ArrayList<>(); // 跟踪每个箱子的已用容量for (int item : sortedItems) {// 寻找最佳箱子int bestBinIndex = -1;int minRemaining = binCapacity + 1; // 初始化为不可能的值for (int i = 0; i < bins.size(); i++) {int remaining = binCapacity - binCapacities.get(i);if (remaining >= item && remaining < minRemaining) {bestBinIndex = i;minRemaining = remaining;}}// 放置物品if (bestBinIndex != -1) {bins.get(bestBinIndex).add(item);binCapacities.set(bestBinIndex, binCapacities.get(bestBinIndex) + item);} else {List<Integer> newBin = new ArrayList<>();newBin.add(item);bins.add(newBin);binCapacities.add(item);}}return bins;}private static void printBins(List<List<Integer>> bins) {System.out.println("使用的箱子数量: " + bins.size());for (int i = 0; i < bins.size(); i++) {List<Integer> bin = bins.get(i);int sum = bin.stream().mapToInt(Integer::intValue).sum();System.out.printf("箱子 %d: %s (总大小: %d)%n", i+1, bin, sum);}}
}

3.2 面向对象优化实现

import java.util.*;public class BinPackingBFDAdvanced {public static void main(String[] args) {List<Integer> items = List.of(4, 8, 5, 1, 2, 3, 6, 7, 9, 4);int binCapacity = 10;BinPackingResult result = packItemsBFD(items, binCapacity);result.printBins();}static class Bin {private final int capacity;private final List<Integer> items;private int currentWeight;public Bin(int capacity) {this.capacity = capacity;this.items = new ArrayList<>();this.currentWeight = 0;}public boolean canAdd(int item) {return currentWeight + item <= capacity;}public void addItem(int item) {if (!canAdd(item)) {throw new IllegalStateException("超出箱子容量");}items.add(item);currentWeight += item;}public int getRemainingCapacity() {return capacity - currentWeight;}public List<Integer> getItems() {return Collections.unmodifiableList(items);}public int getCurrentWeight() {return currentWeight;}}static class BinPackingResult {private final List<Bin> bins;private final int binCapacity;public BinPackingResult(List<Bin> bins, int binCapacity) {this.bins = bins;this.binCapacity = binCapacity;}public void printBins() {System.out.println("使用的箱子数量: " + bins.size());System.out.printf("平均填充率: %.2f%%%n", getAverageFillRate() * 100);for (int i = 0; i < bins.size(); i++) {Bin bin = bins.get(i);System.out.printf("箱子 %2d: %s (总大小: %2d, 填充率: %5.2f%%)%n",i+1, bin.getItems(), bin.getCurrentWeight(),(double)bin.getCurrentWeight() / binCapacity * 100);}}public double getAverageFillRate() {return bins.stream().mapToDouble(bin -> (double)bin.getCurrentWeight() / binCapacity).average().orElse(0);}}public static BinPackingResult packItemsBFD(List<Integer> items, int binCapacity) {// 验证输入validateInput(items, binCapacity);// 排序物品List<Integer> sortedItems = new ArrayList<>(items);sortedItems.sort(Collections.reverseOrder());List<Bin> bins = new ArrayList<>();for (int item : sortedItems) {Bin bestBin = findBestBin(bins, item, binCapacity);if (bestBin != null) {bestBin.addItem(item);} else {Bin newBin = new Bin(binCapacity);newBin.addItem(item);bins.add(newBin);}}return new BinPackingResult(bins, binCapacity);}private static Bin findBestBin(List<Bin> bins, int item, int binCapacity) {Bin bestBin = null;int minRemaining = binCapacity + 1;for (Bin bin : bins) {if (bin.canAdd(item)) {int remaining = bin.getRemainingCapacity() - item;if (remaining < minRemaining) {bestBin = bin;minRemaining = remaining;}}}return bestBin;}private static void validateInput(List<Integer> items, int binCapacity) {if (binCapacity <= 0) {throw new IllegalArgumentException("箱子容量必须为正数");}for (int item : items) {if (item <= 0) {throw new IllegalArgumentException("物品大小必须为正数");}if (item > binCapacity) {throw new IllegalArgumentException("存在物品大小超过箱子容量");}}}
}

3.3 使用TreeSet优化查找

import java.util.*;public class BinPackingBFDWithTreeSet {public static void main(String[] args) {List<Integer> items = List.of(4, 8, 5, 1, 2, 3, 6, 7, 9, 4);int binCapacity = 10;BinPackingResult result = packItemsBFD(items, binCapacity);result.printBins();}static class Bin implements Comparable<Bin> {private final int capacity;private final List<Integer> items;private int currentWeight;public Bin(int capacity) {this.capacity = capacity;this.items = new ArrayList<>();this.currentWeight = 0;}public boolean canAdd(int item) {return currentWeight + item <= capacity;}public void addItem(int item) {if (!canAdd(item)) {throw new IllegalStateException("超出箱子容量");}items.add(item);currentWeight += item;}public int getRemainingCapacity() {return capacity - currentWeight;}public List<Integer> getItems() {return Collections.unmodifiableList(items);}@Overridepublic int compareTo(Bin other) {// 按剩余容量升序排列return Integer.compare(this.getRemainingCapacity(), other.getRemainingCapacity());}}static class BinPackingResult {private final List<Bin> bins;public BinPackingResult(List<Bin> bins) {this.bins = bins;}public void printBins() {System.out.println("使用的箱子数量: " + bins.size());for (int i = 0; i < bins.size(); i++) {Bin bin = bins.get(i);System.out.printf("箱子 %2d: %s (总大小: %2d)%n",i+1, bin.getItems(), bin.currentWeight);}}}public static BinPackingResult packItemsBFD(List<Integer> items, int binCapacity) {// 排序物品List<Integer> sortedItems = new ArrayList<>(items);sortedItems.sort(Collections.reverseOrder());List<Bin> bins = new ArrayList<>();TreeSet<Bin> binTree = new TreeSet<>();for (int item : sortedItems) {// 创建一个临时bin用于查找Bin tempBin = new Bin(binCapacity);tempBin.addItem(binCapacity - item); // 剩余容量=item的箱子// 找到剩余容量 >= item的最小箱子Bin candidate = binTree.ceiling(tempBin);if (candidate != null && candidate.canAdd(item)) {// 从TreeSet中移除,修改后再添加回去binTree.remove(candidate);candidate.addItem(item);binTree.add(candidate);} else {Bin newBin = new Bin(binCapacity);newBin.addItem(item);bins.add(newBin);binTree.add(newBin);}}return new BinPackingResult(bins);}
}

4. 算法分析与性能优化

4.1 时间复杂度分析

  1. 排序阶段:O(n log n)
  2. 装箱阶段
    • 基础实现:O(n²) - 每个物品遍历所有箱子
    • TreeSet优化:O(n log n) - 每次查找O(log n)

4.2 空间复杂度

  • O(n) - 需要存储所有物品和箱子信息

4.3 性能对比测试

import java.util.*;
import java.util.stream.IntStream;public class BFDPerformanceTest {public static void main(String[] args) {int numItems = 100000;int binCapacity = 100;List<Integer> items = generateRandomItems(numItems, binCapacity);// 预热BinPackingBFD.bestFitDecreasing(items.subList(0, 1000), binCapacity);BinPackingBFDAdvanced.packItemsBFD(items.subList(0, 1000), binCapacity);// 测试基础实现long start = System.currentTimeMillis();List<List<Integer>> bins1 = BinPackingBFD.bestFitDecreasing(items, binCapacity);long end = System.currentTimeMillis();System.out.printf("基础BFD实现: %5dms, 箱子数: %d%n", end-start, bins1.size());// 测试高级实现start = System.currentTimeMillis();BinPackingBFDAdvanced.BinPackingResult result = BinPackingBFDAdvanced.packItemsBFD(items, binCapacity);end = System.currentTimeMillis();System.out.printf("高级BFD实现: %5dms, 箱子数: %d, 平均填充率: %.2f%%%n", end-start, result.bins.size(), result.getAverageFillRate()*100);}private static List<Integer> generateRandomItems(int count, int maxSize) {Random random = new Random();return IntStream.range(0, count).map(i -> random.nextInt(maxSize) + 1).boxed().toList();}
}

5. 应用场景与扩展

5.1 实际应用案例

  1. 物流运输

    • 集装箱装载优化
    • 卡车货物配载
    • 航空货运管理
  2. 云计算

    • 虚拟机分配
    • 容器调度
    • 资源分配
  3. 生产制造

    • 原材料切割
    • 生产任务调度
    • 仓库货架管理

5.2 算法扩展变种

  1. 多维BFD

    • 考虑物品的多个维度(长、宽、高)
    • 实现方式:扩展Bin类,添加多维容量检查
  2. 动态BFD

    • 处理动态到达的物品流
    • 实现方式:结合在线算法策略
  3. 成本感知BFD

    • 不同箱子有不同的使用成本
    • 实现方式:在选择箱子时考虑成本因素
  4. 带约束的BFD

    • 某些物品不能放在一起
    • 实现方式:添加冲突检查逻辑

6. 与其他算法对比

6.1 BFD vs FFD

特性BFDFFD
选择策略剩余空间最小的合适箱子第一个能装下的箱子
空间利用率通常更高略低
时间复杂度O(n²)或O(n log n)O(n²)或O(n log n)
实现复杂度稍复杂较简单
适用场景对空间利用率要求高的场景一般场景

6.2 BFD与其他算法对比

  1. Next Fit (NF)

    • 只检查当前箱子,无法回溯
    • 效率低但实现简单
  2. First Fit (FF)

    • 选择第一个能装下的箱子
    • 比BFD快但空间利用率低
  3. Worst Fit (WF)

    • 选择剩余空间最大的箱子
    • 适合希望均匀分布负载的场景

7. 完整Java实现(综合版)

import java.util.*;
import java.util.stream.Collectors;/*** 完整的BFD算法实现,包含所有优化和功能*/
public class ComprehensiveBFD {public static void main(String[] args) {// 示例使用List<Integer> items = generateItems(20, 10);int binCapacity = 10;System.out.println("物品列表: " + items);BFDResult result = pack(items, binCapacity);result.printAnalysis();}/*** BFD装箱结果类*/public static class BFDResult {private final List<Bin> bins;private final int binCapacity;private final long packingTime;public BFDResult(List<Bin> bins, int binCapacity, long packingTime) {this.bins = bins;this.binCapacity = binCapacity;this.packingTime = packingTime;}public int getBinCount() {return bins.size();}public double getAverageFillRate() {return bins.stream().mapToDouble(bin -> (double)bin.getUsedCapacity() / binCapacity).average().orElse(0);}public double getEfficiency() {int totalItems = bins.stream().mapToInt(bin -> bin.getItems().size()).sum();return (double)totalItems / (bins.size() * binCapacity);}public void printAnalysis() {System.out.println("\n装箱分析结果:");System.out.printf("箱子数量: %d\n", getBinCount());System.out.printf("平均填充率: %.2f%%\n", getAverageFillRate() * 100);System.out.printf("算法效率: %.4f\n", getEfficiency());System.out.printf("计算时间: %dms\n", packingTime);System.out.println("\n箱子详情:");bins.forEach(bin -> {System.out.printf("箱子 %2d: %s (使用率: %5.2f%%)%n",bins.indexOf(bin)+1, bin.getItems().stream().map(String::valueOf).collect(Collectors.joining(", ", "[", "]")),(double)bin.getUsedCapacity() / binCapacity * 100);});}}/*** 箱子类*/public static class Bin {private final List<Integer> items;private int usedCapacity;public Bin() {this.items = new ArrayList<>();this.usedCapacity = 0;}public boolean canAdd(int item, int binCapacity) {return usedCapacity + item <= binCapacity;}public void addItem(int item) {items.add(item);usedCapacity += item;}public List<Integer> getItems() {return Collections.unmodifiableList(items);}public int getUsedCapacity() {return usedCapacity;}}/*** 装箱方法*/public static BFDResult pack(List<Integer> items, int binCapacity) {long startTime = System.currentTimeMillis();// 验证输入validateInput(items, binCapacity);// 排序物品(降序)List<Integer> sortedItems = new ArrayList<>(items);sortedItems.sort(Collections.reverseOrder());List<Bin> bins = new ArrayList<>();// 使用TreeMap优化查找: key=剩余容量, value=箱子索引列表TreeMap<Integer, List<Integer>> remainingMap = new TreeMap<>();for (int item : sortedItems) {// 查找最小剩余容量 >= item的箱子Map.Entry<Integer, List<Integer>> entry = remainingMap.ceilingEntry(item);if (entry != null) {// 获取第一个匹配的箱子int binIndex = entry.getValue().get(0);Bin bin = bins.get(binIndex);// 更新TreeMapupdateTreeMap(remainingMap, bin, binIndex, item, binCapacity);// 添加物品到箱子bin.addItem(item);} else {// 创建新箱子Bin newBin = new Bin();newBin.addItem(item);bins.add(newBin);// 计算并添加剩余容量到TreeMapint remaining = binCapacity - item;if (remaining > 0) {remainingMap.computeIfAbsent(remaining, k -> new ArrayList<>()).add(bins.size() - 1);}}}long endTime = System.currentTimeMillis();return new BFDResult(bins, binCapacity, endTime - startTime);}private static void updateTreeMap(TreeMap<Integer, List<Integer>> map, Bin bin, int binIndex, int item, int binCapacity) {// 移除旧的剩余容量记录int oldRemaining = binCapacity - (bin.getUsedCapacity() - item);List<Integer> indices = map.get(oldRemaining);if (indices != null) {indices.remove(Integer.valueOf(binIndex));if (indices.isEmpty()) {map.remove(oldRemaining);}}// 添加新的剩余容量记录int newRemaining = binCapacity - bin.getUsedCapacity();if (newRemaining > 0) {map.computeIfAbsent(newRemaining, k -> new ArrayList<>()).add(binIndex);}}private static void validateInput(List<Integer> items, int binCapacity) {if (binCapacity <= 0) {throw new IllegalArgumentException("箱子容量必须为正数");}for (int item : items) {if (item <= 0) {throw new IllegalArgumentException("物品大小必须为正数");}if (item > binCapacity) {throw new IllegalArgumentException("存在物品大小超过箱子容量");}}}private static List<Integer> generateItems(int count, int maxSize) {return new Random().ints(count, 1, maxSize + 1).boxed().collect(Collectors.toList());}
}

8. 总结

最佳适应递减算法(BFD)是解决装箱问题的高效算法:

  1. 排序+贪心:通过先排序再贪心选择,实现高效装箱
  2. 空间利用率高:通常比FFD获得更好的装箱结果
  3. 灵活可扩展:可适应多种变种问题
  4. 平衡效率:在时间复杂度和空间利用率间取得良好平衡

在实际应用中,BFD算法特别适合:

  • 对空间利用率要求高的场景
  • 物品大小差异较大的情况
  • 需要高质量近似解的场合

通过Java实现时,使用TreeSet/TreeMap等数据结构可以显著提高算法效率,特别是在处理大规模数据时。

更多资源:

https://www.kdocs.cn/l/cvk0eoGYucWA

本文发表于【纪元A梦】!


http://www.hkcw.cn/article/gwOobOGHuU.shtml

相关文章

mysql(十五)

目录 子查询 1.准备工作 2--创建表格 3--插入数据 2.where 子查询单列单个数据 格式 查询 3.where 子查询单列多个数据(in) 格式 查询 使用子查询 4.from 多行多数据 格式 查询 子查询 将select的查询的返回结果 当成另外一个selet语句的内容去使用。 子查询放在()里面 注意…

Unity 环境搭建

Unity是一款游戏引擎&#xff0c;可用于开发各种类型的游戏和交互式应用程序。它由Unity Technologies开发&#xff0c;并在多个平台上运行&#xff0c;包括Windows、macOS、Linux、iOS、Android和WebGL。Unity也支持虚拟现实(VR)和增强现实(AR)技术&#xff0c;允许用户构建逼…

从0开始学习R语言--Day15--非参数检验

非参数检验 如果在进行T检验去比较两组数据差异时&#xff0c;假如数据里存在异常值&#xff0c;会把数据之间的差异拉的很大&#xff0c;影响正常的判断。那么这个时候&#xff0c;我们可以尝试用非参数检验的方式来比较数据。 假设我们有A&#xff0c;B两筐苹果&#xff0c…

NX847NX855美光固态闪存NX862NX865

NX847NX855美光固态闪存NX862NX865 美光固态闪存技术深度解析&#xff1a;NX847、NX855、NX862、NX865的多维探索 一、技术架构与核心优势 美光NX系列固态闪存的卓越性能源于其底层技术的创新突破。以G9 NAND技术为核心的产品线&#xff08;如NX865&#xff09;&#xff0c;…

秋招Day12 - 计算机网络 - UDP

说说TCP和UDP的区别&#xff1f; TCP使用无边界的字节流传输&#xff0c;可能发生拆包和粘包&#xff0c;接收方并不知道数据边界&#xff1b;UDP采用数据报传输&#xff0c;数据报之间相互独立&#xff0c;有边界。 应用场景方面&#xff0c;TCP适合对数据的可靠性要求高于速…

Baklib知识中台重塑企业知识生态

Baklib四库体系构建知识中枢 Baklib通过独创的四库体系&#xff08;显性知识库、隐性经验库、场景案例库、智能模型库&#xff09;&#xff0c;构建起企业知识管理的核心枢纽。显性知识库集中存储制度文档、产品手册等结构化信息&#xff0c;隐性经验库则通过问答社区、专家笔…

字节跳动社招面经 —— BSP驱动工程师(5)

接前一篇文章&#xff1a;字节跳动社招面经 —— BSP驱动工程师&#xff08;4&#xff09; 本文内容参考&#xff1a; ARM64架构启动流程_arm64 linux kernel 启动流程-CSDN博客 特此致谢&#xff01; 上一回讲解了“嵌入式充电站”发的一篇文章字节跳动社招面经——BSP驱动工…

超越与沉浸:关于意识觉醒的量子化生存艺术

一、现象世界的认知架构&#xff1a;从AR渲染到神经编译 人类意识系统犹如搭载生物算法的增强现实&#xff08;AR&#xff09;设备&#xff0c;每秒将4000万比特的原始感官数据&#xff0c;通过神经编译引擎压缩成40比特的认知全息图。在这个过程中&#xff1a; 海马体材质库自…

自主设计一个DDS信号发生器

DDS发生器 DDS信号发生器是直接数字频率合成技术&#xff0c;采用直接数字频率合成(Direct Digital Synthesis&#xff0c;简称DDS)技术&#xff0c;把信号发生器的频率稳定度、准确度提高到与基准频率相同的水平&#xff0c;并且可以在很宽的频率范围内进行精细的频率调节。采…

浏览器网站禁止黏贴,但是要交作业怎么快速黏贴

出现的问题&#xff1a; 写这篇博客的原因&#xff1a;学校最近要求使用 iwrite 写英语作文&#xff0c;但是浏览器禁止黏贴&#xff0c;我们自己只能手动输入&#xff0c;但是作为程序猿的我想到了一个很好的解决方案。 解决思路&#xff1a; 我们直接在浏览器的控制台的源代码…

CAN通讯协议中各种参数解析

1.各种参数缩写 2.多帧传输时间参数解析 - Sender&#xff08;左侧&#xff09; 指的是 多帧数据的发送者&#xff0c;也就是&#xff1a; ECU&#xff08;被测系统 / 响应方&#xff09; - Receiver&#xff08;右侧&#xff09; 指的是 多帧数据的接收者&#xff0c;也就是…

第十二节:第五部分:集合框架:Set集合的特点、底层原理、哈希表、去重复原理

Set系列集合特点 哈希值 HashSet集合的底层原理 HashSet集合去重复 代码 代码一&#xff1a;整体了解一下Set系列集合的特点 package com.itheima.day20_Collection_set;import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.…

deepseek原理和项目实战笔记2 -- deepseek核心架构

混合专家&#xff08;MoE&#xff09; ​​混合专家&#xff08;Mixture of Experts, MoE&#xff09;​​ 是一种机器学习模型架构&#xff0c;其核心思想是通过组合多个“专家”子模型&#xff08;通常为小型神经网络&#xff09;来处理不同输入&#xff0c;从而提高模型的容…

迈向分布式智能:解析MCP到A2A的通信范式迁移

智能体与外部世界的桥梁之言&#xff1a; 在深入探讨智能体之间的协作机制之前&#xff0c;我们有必要先厘清一个更基础的问题&#xff1a;**单个智能体如何与外部世界建立连接&#xff1f;** 这就引出了我们此前介绍过的 **MCP&#xff08;Model Context Protocol&…

TCP/IP协议精华总结pdf分享

hi &#xff0c;大家好&#xff0c;应小伙伴们的要求&#xff0c;上次分享了个人的一些学习和职场经验&#xff0c;其中网络协议PDF文档是我之前学习协议的时候总结一些精华知识&#xff0c;网络属于基本功&#xff0c;是互联网必备知识&#xff0c;我深信掌握好核心20%知识&am…

齐次变换矩阵与运动旋量的指数映射

在三维空间中&#xff0c;刚体的位姿&#xff08;位置和姿态&#xff09;可以通过齐次变换矩阵进行描述。齐次变换矩阵是一种 44 的矩阵&#xff0c;其一般形式为&#xff1a; T [ R p 0 1 ] T\begin{bmatrix}R&p\\0&1\end{bmatrix} T[R0​p1​] 其中&#xff0c; R …

MySQL DDL操作全解析:从入门到精通,包含索引视图分区表等全操作解析

目录 一、DDL 基础概述 1.1 DDL 定义与作用 1.2 DDL 语句分类 1.3 数据类型与存储引擎 1.3.1 数据类型 1.3.2 存储引擎差异 二、基础 DDL 语句详解 2.1 创建数据库与表 2.1.1 创建数据库 2.1.2 创建表 2.2 修改表结构 2.2.1 添加列 2.2.2 修改列属性 2.2.3 删除列…

torch.randn vs torch.rand

1 分布类型&#xff1a; randn&#xff1a;生成标准正态分布&#xff08;均值 0&#xff0c;标准差 1&#xff09; rand&#xff1a;生成 [0, 1) 区间的均匀分布 2 数值范围&#xff1a; randn&#xff1a;可能产生负数&#xff08;范围 (-∞, ∞)&#xff09; rand&#xff…

NLP学习路线图(十九):GloVe

自然语言处理&#xff08;NLP&#xff09;的核心挑战在于让机器理解人类语言的丰富含义。词向量&#xff08;Word Embeddings&#xff09;技术通过将词语映射到高维实数空间&#xff0c;将离散的符号转化为连续的向量&#xff0c;为NLP任务奠定了坚实基础。在众多词向量模型中&…

极客时间:用 FAISS、LangChain 和 Google Colab 模拟 LLM 的短期与长期记忆

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…