-
在CUDA编程中,一个CUDA Kernel是由众多线程(threds)组成,而这些线程又可以被组织成一个或多个block块。在同一线程块中,线程ID是从0开始连续编号的,可以通过内置变量threadIdx来获取:// 获取本线程的索引,blockIdx 指的是线程块的索引,blockDim 指的是线程块的大小,threadIdx 指的是本线程块中的线程索引 int tid = blockIdx.x * blockDim.x + threadIdx.x; 以对图像的归一化处理为例,需要对图片中的每一个像素点的三个通道值分别除以255,相比于使用CPU进行串行计算,我们可以使用CUDA核函数创建更多的线程和线程块来充分利用GPU的并行处理能力:// 计算需要的线程总量(高度 x 宽度):640*640=409600 int jobs = dst_height * dst_width; // 一个线程块包含256个线程 int threads = 256; // 计算线程块的数量(向上取整) int blocks = ceil(jobs / (float)threads); // 调用kernel函数 preprocess_kernel<<<blocks, threads>>>( img_buffer_device, dst, dst_width, dst_height, jobs); // 函数的参数 这里我们定义每个线程块的线程数量为256,线程块的数量为ceil(jobs / (float)threads),总的线程总量要大于等图片的像素数量。当启动Kernel函数时,GPU上的每个线程都会执行相同的程序代码,从而实现更高效的并行计算,函数具体实现如下:// 一个线程处理一个像素点 __global__ void preprocess_kernel( uint8_t *src, float *dst, int dst_width, int dst_height, int edge) { int tid = blockDim.x * blockIdx.x + threadIdx.x; if (tid >= edge) return; int dx = tid % dst_width; // 计算当前线程对应的目标图像的x坐标 int dy = tid / dst_width; // 计算当前线程对应的目标图像的y坐标 // normalization(对原图中(x,y)坐标的像素点3个通道进行归一化) float c0 = src[dy * dst_width * 3 + dx * 3 + 0] / 255.0f; float c1 = src[dy * dst_width * 3 + dx * 3 + 1] / 255.0f; float c2 = src[dy * dst_width * 3 + dx * 3 + 2] / 255.0f; // bgr to rgb float t = c2; c2 = c0; c0 = t; // rgbrgbrgb to rrrgggbbb // NHWC to NCHW int area = dst_width * dst_height; float *pdst_c0 = dst + dy * dst_width + dx; float *pdst_c1 = pdst_c0 + area; float *pdst_c2 = pdst_c1 + area; *pdst_c0 = c0; *pdst_c1 = c1; *pdst_c2 = c2; } 其中tid是本线程的索引,dst_width和dst_height是图像的宽和高,edge是图片的像素数量,每一个线程处理一个像素点。由于线程索引是从0开始计数的,我们要确保tid不能超过图片的像素数量edge:int tid = blockDim.x * blockIdx.x + threadIdx.x; if (tid >= edge) return; 由于图像数据以行优先(row-major)顺序连续存储在内存中,每个像素由3个字节表示(BGR)。为了获取每个线程所处理的像素点在内存中的起始位置,我们可以先计算当前线程所对应图像的x和y坐标即dx和dy:int dx = tid % dst_width; // 计算当前线程对应的目标图像的x坐标 int dy = tid / dst_width; // 计算当前线程对应的目标图像的y坐标 然后获取当前线程所处理的像素点在内存中的起始位置:dy * dst_width * 3 + dx * 3,*3是因为每个像素点有3个通道值,在内存中的排列方式为:BGRBGRBGR...,最后再/255对原图中(x,y)坐标的像素点3个通道值进行归一化:// normalization float c0 = src[dy * dst_width * 3 + dx * 3 + 0] / 255.0f; float c1 = src[dy * dst_width * 3 + dx * 3 + 1] / 255.0f; float c2 = src[dy * dst_width * 3 + dx * 3 + 2] / 255.0f; dy * dst_width * 3:定位到第dy行的起始位置dx * 3:在当前行中定位到第dx个像素的起始位置+ 0, + 1, + 2:分别访问B、G、R三个通道的值除以255交换变量做BGR到RGB的通道转换:// bgr to rgb float t = c2; c2 = c0; c0 = t; 目标图像(RGB)像素点在内存中的排列方式为RRR...GGG...BBB,当前像素点R通道的值在目标图像中内存地址为(dst + dy * dst_width + dx),G通道的值在目标图像中内存地址为(dst + dy * dst_width + dx) + area,加上1个通道的偏移量area,以此类推,完成对图像的通道转换:// NHWC to NCHW // rgbrgbrgb to rrrgggbbb int area = dst_width * dst_height; float *pdst_c0 = dst + dy * dst_width + dx; float *pdst_c1 = pdst_c0 + area; float *pdst_c2 = pdst_c1 + area; *pdst_c0 = c0; *pdst_c1 = c1; *pdst_c2 = c2;
-
背景本月内容重点聚焦 AI Agent 体系、知识图谱构建、智能体协同与时间序列模型优化 四大方向,整体呈现出从“理论机制 → 算法设计 → 系统协同 → 工程落地”的连贯研究路径,体现了论坛技术生态持续向自主架构、可解释安全、可进化智能体体系推进的趋势。以下从内容视角给出核心总结干货好文合集【技术干货】 智能体知识更新机制:增量式知识图谱构建与融合技术https://bbs.huaweicloud.com/forum/thread-0250198474355591003-1-1.html大模型 Agent 体系中的通信协议抽象https://bbs.huaweicloud.com/forum/thread-0213198474959123001-1-1.html基于 LSTM-Transformer 混合架构的跨尺度时间序列预测模型研究https://bbs.huaweicloud.com/forum/thread-02126198573374469002-1-1.html智能体目标冲突解决多目标优化中的权重动态调整策略https://bbs.huaweicloud.com/forum/thread-0235198666987524003-1-1.html多 Agent 系统的一致性协议:Paxos 与 Raft 在智能体协同中的应用https://bbs.huaweicloud.com/forum/thread-02117198731401998002-1-1.html高不确定环境下智能体协同行为的分布式一致性可观测性指标体系构建https://bbs.huaweicloud.com/forum/thread-02127198732557561001-1-1.html本期 11 月人工智能技术内容整体呈现出从“模型能力”向“系统级智能”迈进的方向,重点聚焦在 智能体知识演化、协同通信协议、一致性协作机制、多目标优化与跨尺度预测模型 等关键能力建设。可以看到,研究不再停留在单一模型性能,而是进一步关注 可扩展、可协同、可持续、可解释 的智能体系架构,为未来的自主智能体生态与真实业务落地奠定了更具工程价值的理论与方法基础。总结从本月内容来看,论坛的技术研究主题已经明显从单点模型能力向体系化智能工程演进,重点围绕 智能体(AI Agent)在复杂环境下的知识表达、演化机制、协同通信、目标优化以及分布式一致性 等核心能力展开。这类内容体现出一个趋势:行业正在从“把模型用好”转向“让智能体长期、稳定、可控地运行”。尤其是增量式知识图谱与智能体知识更新方法的探讨,说明大家开始关注智能体在任务连续性与知识生命周期管理方面的能力,这对于构建具备自适应、可记忆、可演化特征的长期运行智能系统至关重要。与此同时,大模型驱动的 Agent 体系通讯协议抽象研究,为未来智能体间的互联互通、跨系统协同与多工具调用提供了统一框架,这类工作往往看似基础,但会在未来成为 AI 工程体系的“水电煤标准”。在算法层面,时间序列模型的混合架构探索(LSTM + Transformer)说明研究者已经意识到在真实业务中,数据特征往往具有不同的尺度与依赖结构,单一模型已难以覆盖所有情况,需要更“工程化”的组合模型和优化思路。在智能体决策部分,多目标冲突动态权重与分布式协同一致性研究,为多智能体系统在无人驾驶、智能制造、边缘计算与多无人机系统等场景中提供了可执行的理论参考。尤其是将 Paxos/Raft 等一致性协议引入智能体协作框架,以及构建可观测性指标体系,体现出研究者已经开始从“如何让 AI 协同?”升级到“如何确保协同的正确性、可信性与可监测性?”。这类工作将成为未来智能体系统安全、稳定、可控的重要基础。总的来看,11 月的内容具有明显的研究前瞻性 + 工程实践性双重属性,呈现出 AI 研究从模型时代向智能体时代转变的特征:从精准预测到可解释决策、从单体智能到协同智能、从静态能力到动态演化。可以预见,未来的技术讨论会进一步拓展到智能体安全性、可信度评估、标准协议体系与跨行业落地框架,AI 不再只是推理工具,而是将逐步成为具有知识、能力、策略与协作能力的数字主体。
-
随着网络攻击手段愈加隐蔽与自动化,传统依赖特征库与规则匹配的恶意代码检测模式正逐渐面临瓶颈。一方面,新型威胁呈现出“低特征、高多态、跨架构、跨平台”特征;另一方面,安全攻防双方的迭代周期正在显著缩短,人工逆向分析、人肉排查可疑样本的模式难以匹配当下的响应需求,导致安全体系在效率、精度、可解释性与持续演进能力上产生显著缺口。本次发布的华为 & 瑞星 DCS AI 安全解决方案及配套 AI 安全一体机拥有“计算-存储-网络-安全-运维”的一体化能力。大家怎么看?
-
高不确定环境下智能体协同行为的分布式一致性可观测性指标体系构建一、背景与研究动机多智能体系统(Multi-Agent System, MAS)在现实世界中越来越常见,例如无人机编队、仓储机器人调度、灾难救援协作、海面无人舰群、群智感知网络等。它们在执行任务时常处于高不确定环境——信息不完备、通信随机丢包、感知噪声、多主体异构化、策略更新异步,这些因素使得协同行为的一致性与可信决策监控成为关键难题。传统一致性研究往往强调算法正确性,但在工程部署中,我们更关注:系统是否可被观测并评价何时出现协同退化退化是否可提前预警如何量化一致性的稳定性、公平性、收敛性因此,我提出一套 “分布式一致性可观测性指标体系”,它不是为了替代现有共识算法,而是用于评估与诊断协同行为质量,使得系统具备自感知与闭环反馈能力。二、分布式一致性可观测性的基本思想可观测性在控制理论中指系统内部状态是否能从外部输出推断。但在多智能体协同任务中,我们不需要恢复所有内部状态,而应关注:行为一致性是否可量化差异来源是否可区分异常主体是否可定位协同风险是否可预测我将可观测信息分为三类:信息类别描述示例行为观测输出结果是否趋同路径误差、速度差、策略倾向度认知观测决策内部理由是否趋同reward梯度方向、一致意图编码通信观测共享信息质量是否可靠丢包率、延迟方差、编码相似度三、指标体系设计(原创框架)整个指标体系由 4类核心指标 + 1个风险评估模块 组成:1. 收敛一致性指标(Convergence Cohesion)用于衡量协同行为在时间维度上是否趋向目标一致性:均值偏移差(Mean Deviation Drift)收敛趋势斜率(Trend Slope)稳定区间长度(Stable Window Length)2. 结构一致性指标(Structural Homogeneity)用于判断多智能体是否在策略结构上保持同构或可映射性:策略表示相似度(Embedding Similarity)决策特征投影距离(Feature Distance)异构影响传播系数(Hetero Influence Ratio)3. 通信可靠性指标(Distributed Information Fidelity)反映信息供给是否支持协同行为持续有效:丢包均值与变异度通信拓扑连通系数信息冗余度评分4. 异常可定位性指标(Agent Fault Identifiability)用于评估错误来源是否能快速定位:局部一致性均值差异常单主体影响边际分析团队熵突变点识别5. 协同风险评分模型(协同温度)我将风险模型称为 “Collaborative Temperature (CT)”:越高代表越不稳定。四、基于 Python 的实验性可观测指标实现示例下面给出一个可运行的完整实验框架示例:模拟 5 个智能体以随机噪声同步收敛到目标值,通过自定义指标评估协同质量。代码示范import numpy as np import matplotlib.pyplot as plt # 模拟5个Agent的状态变化,目标为 10 np.random.seed(42) num_agents = 5 steps = 50 target = 10 # 高噪声环境仿真 states = np.zeros((steps, num_agents)) states[0] = np.random.uniform(0, 3, size=num_agents) for t in range(1, steps): noise = np.random.normal(0, 0.8, size=num_agents) # 模拟基于邻域平均的弱一致性更新过程 states[t] = states[t-1] + 0.25 * (target - states[t-1]) + noise # 指标函数部分 def mean_deviation(states): return np.mean(np.abs(states - np.mean(states, axis=1, keepdims=True)), axis=1) def convergence_trend(states): # 越趋近目标,趋势值越小 return np.mean(np.abs(states - target), axis=1) def stability_window(metric, threshold=0.2, window=5): count = 0 for i in range(len(metric) - window): if np.all(metric[i:i+window] < threshold): count += 1 return count # 得到指标 md = mean_deviation(states) ct = convergence_trend(states) stable_win = stability_window(ct) print(f"收敛偏差趋势末值: {ct[-1]:.4f}") print(f"行为一致性末期平均偏差: {md[-1]:.4f}") print(f"稳定窗口计数: {stable_win}") # 绘图观察 plt.plot(ct, label="Convergence Trend") plt.plot(md, label="Mean Deviation") plt.legend() plt.title("Distributed Consensus Observability Indicators") plt.xlabel("Time Step") plt.ylabel("Indicator Value") plt.show() 输出解释运行后你会看到两条曲线:Convergence Trend 趋势线不断下降 → 表明协作逐步有效Mean Deviation 趋于稳定 → 表明行为一致性提高若出现中途突然跃升,则说明可能存在异常节点或噪声冲击这就是可观测指标体系的意义:不仅判断最终结果是否一致,更关注过程中是否具备稳健协同能力。五、体系的工程落地建议场景推荐指标优先级无人机航迹编队收敛一致性 + 通信可靠性自主仓储机器人调度异常可定位性 + 结构一致性分布式能源经济调度收敛一致性 + 稳定窗口多车协同感知 L4信息冗余度 + 协同风险温度特别强调一点:真实系统不要只看最终误差,要重点看过程稳定性与异常可解释性。六、个人总结做多智能体协同研究的人往往太注重算法变体,而忽视可观测性评价体系的工程价值。在高不确定环境下,仅仅“收敛”是不够的,还必须:可测量可解释可定位可预警我认为未来值得重点研究的两个方向:指标体系与可视化监控仪表盘结合指标体系与自适应策略恢复机制融合多智能体协同的终点不是算法论文,而是 复杂真实场景的稳定落地。
-
多 Agent 系统的一致性协议:Paxos 与 Raft 在智能体协同中的应用近年来,多智能体(Multi-Agent)系统已经从理论探索走向可落地应用,例如智能仓储机器人群调度、自动驾驶车队协同、智能电网调度以及分布式金融决策系统。随着智能体数量的增加,如何在异步网络、潜在故障、节点掉线或网络抖动场景下保持决策一致性成为系统能否稳定运行的核心挑战。我在工程实践中逐渐意识到:多智能体系统的核心不是智能,而是协同与共识。过度强调模型精度,而忽略分布式一致性,最终系统必然会在真实环境下失控。为了解决多 Agent 的协同一致性问题,传统分布式一致性协议如 Paxos、Raft 依然具有极高的参考与改造价值。一、为什么多 Agent 系统需要一致性协议?自然智能的群体行为(例如蚂蚁协作、蜜蜂择巢决策、迁徙队列中的领头机制)都存在某种隐含的“共识形成过程”。人工多智能体系统如果缺乏一致性设计,会出现以下问题:场景问题表现影响机器人协同搬运多机器人同时改变目标点撞车、死锁金融多代理决策策略节点意见不一致风控失效、资产损失无人机编队领航信息不一致队形瓦解智慧交通多路口调度冲突交通拥堵甚至事故因此,一个足够健壮的智能体协同系统必须具备:领导者选举能力多节点提案与投票机制故障节点可替代日志或指令严格一致这就是 Paxos 与 Raft 仍然被视为“分布式共识基础设施”的原因。二、Paxos 与 Raft 的适用性比较(基于个人实践)以下是我对两者结合 AI 多 Agent 实践的评价,而不是书本理论:维度PaxosRaft工程建议学习难度难度陡峭、论文风格抽象可读性更强、思路清晰企业更易落地 Raft领导者机制灵活但复杂固定 Leader、逻辑简单推荐易维护系统使用 Raft容错切换复杂清晰、可快速恢复对实时系统更友好日志复制有但难理解明确、结构直观适合 Agent 状态同步实际应用偏理论与特殊场景Kubernetes、etcd、TiKV 等主流工业共识首选 Raft结论:Paxos 适合顶尖研究场景,而 Raft 更适合规模化工程落地。在智能体系统中,如果节点数量大于 5 且具备实时性要求,Raft 明显更具优势。三、将 Raft 思想用于多 Agent 协同的核心要点我的工程经验中,直接照搬 Raft 并不可行,需要做智能体场景改造:原 Raft 机制在多 Agent 场景的改造建议日志复制替换为“共享任务/意图序列”同步Leader 选举可加入“能力权重 + 健康评分”策略心跳检测扩展为状态、传感器、位置、算力维度任期 (Term)用于记录“策略版本迭代号码”例如智能车队中,如果仅用定时心跳检测,会忽略“感知衰减、路径可信度、能耗风险”等因素,因此需要增维度一致性验证机制。四、简单可运行的 Python Raft 风格 Agent 协同示例(最小可行版本)说明:仅为学习演示,不包含完整网络通信、日志压缩、持久化与异常注入重点演示 Leader 选举与一致任务提交4.1 环境依赖pip install fastapi uvicorn pydantic requests4.2 代码示例:简化版 Raft 风格 Agent 共识agent_node.pyimport random import time import requests from threading import Thread from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() state = { "role": "follower", "term": 0, "leader": None, "log": [] } node_id = random.randint(1000, 9999) peers = [] # 其他节点地址,如 ["http://localhost:8001", "http://localhost:8002"] class Task(BaseModel): command: str term: int @app.get("/heartbeat") def heartbeat(term: int): if term >= state["term"]: state["term"] = term state["role"] = "follower" return {"status": "ok"} @app.post("/append") def append(task: Task): if task.term >= state["term"]: state["log"].append(task.command) return {"status": "committed"} return {"status": "reject"} def start_election(): state["role"] = "candidate" state["term"] += 1 votes = 1 # 自己一票 for peer in peers: try: res = requests.get(f"{peer}/heartbeat", params={"term": state["term"]}) if res.status_code == 200: votes += 1 except: pass if votes >= (len(peers) + 1) // 2 + 1: state["role"] = "leader" state["leader"] = node_id print(f"Node {node_id} 成为 Leader") else: state["role"] = "follower" def heartbeat_loop(): while True: if state["role"] == "leader": for peer in peers: try: requests.get(f"{peer}/heartbeat", params={"term": state["term"]}) except: pass time.sleep(1) Thread(target=heartbeat_loop, daemon=True).start() 运行多个实例即可模拟节点间选举,每次执行可观察到不同节点成为 Leader。4.3 扩展方向若用于真实智能体系统(如无人机群控),还需加入:任务冲突检测节点信誉度动态权重迁移冷/热备份领导机制状态快照(对应 Raft snapshot)五、个人经验总结为了避免“概念理解正确但工程完全跑不通”的情况,我在实际项目中总结过以下更具体、更具有现实意义的经验点,它们比理论要更“辣眼睛”,但往往更有用:5.1 一致性成本永远存在,不要幻想“零额外代价”多智能体系统的协同一致性本质上是 可靠性换性能 的过程。你想要每个节点决策超级灵活,那么一致性系统一定受限;你想要决策一致且安全,那么系统延迟一定会上升。因此,一致性协议并不是性能优化工具,而是系统安全底线。在实际落地中,我一般采用:场景策略选择无需全局同步、允许局部偏差放弃一致性,用局部策略 + 信誉约束有中度协作关系、偶尔分歧可容忍半一致性:Leader + Lazy Sync高安全、高精度、不可差错采用强一致性协议换句话说,不要为了“技术看起来高级”而滥用 Paxos/Raft。5.2 Leader 并非永远最聪明,而是最可靠很多团队把 Leader 想象成“大脑”,甚至尝试把最高算力、最佳模型效果者设为 Leader,这是典型误区。在智能体协同场景中,Leader 的首要属性不是智能,而是稳定性。如果 Leader 过于繁忙、承担多线程规划或计算,很可能变成新的系统瓶颈甚至故障点。因此,我的建议是:职能适合角色复杂策略推演、模型评估智能工作节点 (Compute Agent)协调、广播、状态管理、容错Leader 节点(可相对“笨”)这是工程设计中最常见、但被初学者忽视的方向 —— Leader 应该足够可替代。5.3 必须监控“智能一致性”而不是仅监控“网络一致性”很多团队仅监控心跳、延迟、丢包率,但完全忽略了任务、策略与价值一致性。举例说明:如果五个无人机节点策略模型版本不一致,即便网络连接很好,行动仍然会崩溃。因此我在项目中加入了以下监控指标:模型版本号一致性策略哈希校验一致性传感器可信度评分一致性Agent 内部负载健康度最近 3 次任务决策偏差度一句话总结:共识验证不能只验证系统状态,还要验证智能状态。5.4 日志复制不应该只有“日志”,还应包含“因果链路”传统 Raft 日志复制是记录事件序列,而智能体领域需要更进一步 —— 记录行动的认知理由。例如无人机在遇到障碍时转弯:普通日志智能体增强日志turn_leftturn_left ;reason=low_confidence:front_map当未来回放协作轨迹时,系统可以评估行为合理性,而不是只能看到行为结果。这在故障分析与安全系统中极其关键。六、多 Agent 一致性未来演化方向(个人观点)我认为现有 Paxos 与 Raft 在智能体协作中还属于临界适用阶段,未来至少会往以下三个方向演进:6.1 从“节点一致性”转向“知识一致性”未来一致性协议需要同步决策依据,而不仅是同步指令。例如采用:因果图谱(Causal Graph)策略嵌入向量(Policy Embedding)置信度与风险等级同步6.2 引入策略权重动态迁移一致性不同 Agent 会有不同能力与专业性,未来可能采用:任务领域投票专家代理(Expert Agent)提案优先信任网络驱动一致性(Trust-aware Consensus)6.3 结合多模态感知的共识验证未来系统应该不仅基于 ID 投票,而是基于世界模型(World Model)推断共识,例如:视觉感知一致性地图相似度一致性置信度分布一致性七、结语在智能体技术热潮中,我看到大量开发者热衷构建所谓“多 Agent 协作系统”,但最终只是多个独立任务脚本堆叠在一起。真正的协作需要 分布式系统韧性 + 感知一致性 + 策略共识,而 Paxos 与 Raft 正是进入这个领域的钥匙。共识协议不是智能体系统的加分项,而是底层可靠性基石。缺乏安全一致性机制的多 Agent 系统,最终只是在做多人单机模式。
-
KNN算法:AI的“物以类聚”社交法则在人类社交中,我们常通过“物以类聚,人以群分”的直觉判断新朋友的相似性——比如,一个热爱编程、常泡图书馆的人,大概率会和另一个技术极客成为好友。这种基于“邻近性”的社交逻辑,正是机器学习中**K近邻算法(K-Nearest Neighbors, KNN)**的核心思想。KNN不依赖复杂的数学公式,而是通过“找邻居”这种最朴素的方式完成分类或回归任务。本文将用生活化的比喻拆解KNN的原理,并探讨它如何在AI世界中实现“以邻为鉴”的智慧。一、KNN的社交哲学:你的圈子决定你是谁1. 从社交圈到KNN:相似性即投票权想象你搬到一个新社区,想快速判断一家餐厅是否值得光顾。你会怎么做?方法1:随机选一家(碰运气);方法2:观察邻居的选择——如果附近5家餐厅中4家都排队,你可能会跟风(KNN逻辑)。KNN的核心假设:相似样本具有相似标签(如口味相近的人会选择同一家餐厅);通过统计邻居的“投票”或“平均值”决定新样本的归属。类比社交场景:分类问题:判断一个人是“运动爱好者”还是“宅家达人”,只需看他最近的K个朋友中多数属于哪类;回归问题:预测一个人的月消费水平,可取他最近K个邻居的消费平均值。2. KNN的“社交参数”:K值与距离度量KNN的“社交规则”由两个关键参数决定:K值(邻居数量):K=1时,完全依赖“最近的一个朋友”(易受极端值影响,如被一个土豪邻居拉高消费预期);K=N(样本总数)时,直接取全局平均(失去个性化,如忽略社区内的小圈子文化)。经验法则:K通常取奇数(避免分类投票平票),并通过交叉验证选择最优值。距离度量:社交中常用“兴趣重叠度”衡量相似性,KNN中则用数学距离:欧氏距离(直线距离):适用于连续特征(如年龄、收入);曼哈顿距离(城市街区距离):适用于方向性强的特征(如坐标移动);余弦相似度:适用于文本、推荐系统(如用户对电影的评分模式)。案例:预测用户是否喜欢电影《星际穿越》:计算该用户与所有其他用户的“电影偏好距离”(如对科幻片评分差异);找到K个距离最近的邻居,统计其中喜欢该电影的比例。二、KNN的“社交能力”拆解:三大核心步骤1. 第一步:计算“社交距离”对每个新样本(如新用户A),计算其与所有已知样本(如数据库中所有用户)的距离。示例:已知用户数据:用户ID年龄科幻片评分喜剧片评分标签(是否喜欢《星际穿越》)U12595是U23078否U32286是新用户A:年龄24,科幻片评分8.5,喜剧片评分5.5。计算A与U1的欧氏距离:(24−25)2+(8.5−9)2+(5.5−5)2=1+0.25+0.25≈1.22\sqrt{(24-25)^2 + (8.5-9)^2 + (5.5-5)^2} = \sqrt{1 + 0.25 + 0.25} \approx 1.22 (24−25)2+(8.5−9)2+(5.5−5)2=1+0.25+0.25≈1.22同理计算A与U2、U3的距离,得到距离列表:U1(1.22)、U3(0.87)、U2(5.92)。2. 第二步:选择“K个最近邻居”按距离从小到大排序,选择前K个样本。若K=2,邻居为U3(0.87)、U1(1.22);若K=3,邻居为U3、U1、U2(5.92)。关键点:K值过小(如K=1)易受噪声干扰(如U1可能偶然给喜剧片低分,但实际喜欢科幻片);K值过大(如K=3)可能引入不相关邻居(如U2的偏好与A差异较大)。3. 第三步:投票或平均“社交意见”分类任务:统计K个邻居中多数类的标签(如K=2时,U3和U1均喜欢《星际穿越》,预测A“喜欢”);回归任务:取K个邻居标签的平均值(如预测房价时,取K个邻居房价的平均作为预测值)。扩展:加权投票:根据距离远近分配权重(如距离越近,投票权重越高);拒绝选项:若K个邻居中最大投票比例低于阈值(如55%),可标记为“不确定”。三、KNN的优缺点:简单背后的“社交困境”优点简单直观:无需训练过程(“懒惰学习”),适合快速原型开发;适应性强:对数据分布无假设(如无需假设数据服从正态分布);多任务通用:既能分类(如垃圾邮件检测)又能回归(如房价预测);4 抗噪声能力:通过K值投票平滑个别异常值(如K=5时,1个错误标签影响有限)。缺点计算成本高:需存储所有训练数据,预测时需计算新样本与所有样本的距离(大数据场景效率低);维度灾难:特征过多时,距离度量失效(如100维空间中,所有样本距离几乎相等);样本不平衡敏感:若某类样本极少,可能被多数类“淹没”(如欺诈检测中,欺诈样本占比<1%时易漏检);K值选择困难:需通过交叉验证调参,且不同场景最优K值差异大。改进方案:使用KD树或球树优化距离计算(减少计算量);对高维数据先进行降维(PCA、t-SNE);对类别不平衡数据采用加权投票(如欺诈样本的投票权重更高)。四、实战应用:KNN能解决哪些“社交型”问题?1. 分类问题:从社交标签到AI判断场景:用户画像、情感分析、图像识别、医疗诊断。案例:推荐系统:根据用户历史行为(如购买、评分),找到相似用户(K近邻)推荐商品;手写数字识别:将新数字图像与已知数字图像库对比,取K个最相似的图像的标签投票。2. 回归问题:从群体平均到个性化预测场景:房价预测、销量预估、气温变化、传感器数据建模。案例:共享单车需求预测:根据历史数据中相似时间、相似地点的骑行量,预测当前需求;电力负荷预测:结合历史天气、节假日等因素,找到相似日期的用电量平均值。3. 异常检测:识别“不合群”的样本场景:金融欺诈、工业缺陷检测、网络入侵、社交网络中的虚假账号。案例:信用卡欺诈检测:若某笔交易的K个最近邻居中多数为正常交易,则标记为可疑;社交机器人识别:根据用户发帖频率、互动模式等特征,找到相似真实用户,异常值可能为机器人。4. 数据补全:用邻居“填补空白”场景:缺失值填充、图像修复、时间序列插值。案例:用户年龄缺失:根据该用户的其他特征(如收入、职业),找到K个相似用户的年龄平均值填充;老照片修复:用相似图像块(如纹理、颜色分布)替换损坏区域。五、动手实践:用Python实现KNN分类from sklearn.datasets import load_iris from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report import matplotlib.pyplot as plt import numpy as np # 加载数据(鸢尾花数据集) data = load_iris() X, y = data.data, data.target feature_names = data.feature_names target_names = data.target_names # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 训练KNN模型(K=5,使用欧氏距离) knn = KNeighborsClassifier(n_neighbors=5, metric='euclidean') knn.fit(X_train, y_train) # 预测与评估 y_pred = knn.predict(X_test) print("准确率:", accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred, target_names=target_names)) # 可视化K值对准确率的影响(简化版:实际需交叉验证) k_values = range(1, 20) accuracies = [] for k in k_values: knn = KNeighborsClassifier(n_neighbors=k) knn.fit(X_train, y_train) accuracies.append(knn.score(X_test, y_test)) plt.plot(k_values, accuracies, marker='o') plt.xlabel('K Value') plt.ylabel('Accuracy') plt.title('KNN Performance vs. K Value') plt.xticks(k_values) plt.grid() plt.show() 输出示例:准确率: 0.9777777777777777 precision recall f1-score support setosa 1.00 1.00 1.00 19 versicolor 1.00 0.92 0.96 13 virginica 0.93 1.00 0.96 13 accuracy 0.98 45 macro avg 0.98 0.97 0.97 45 weighted avg 0.98 0.98 0.98 45 六、结语:KNN——AI世界的“朴素社交达人”KNN用“物以类聚”的直觉,构建了一个简单却强大的AI模型。它没有复杂的数学推导,却能在分类、回归、异常检测等任务中表现优异;它像一位善于观察的社交达人,通过“找邻居”快速融入新环境。当然,KNN的“社交能力”也有局限——面对海量数据或高维空间时,它可能显得笨拙。但正是这种朴素性,让它成为机器学习入门者的第一站,也是工业界快速验证想法的利器。下次当你需要解决一个“相似性判断”问题时,不妨试试让KNN帮你“交个朋友”!
-
随机森林:多个“笨模型”组队如何打败“学霸”在机器学习领域,有一个反直觉的现象:一群“笨模型”通过组队合作,往往能超越单个“学霸模型”的性能。随机森林(Random Forest)正是这一理念的典型代表——它通过集成大量简单的决策树(常被视为“弱学习者”),最终构建出一个强大的预测模型。本文将用生活化的比喻拆解随机森林的原理,并探讨它为何能成为工业界的“万能工具”。一、从“三个臭皮匠”到随机森林:集体的智慧1. 单棵决策树的局限性:学霸的“偏科”问题决策树是一种直观但脆弱的模型:优点:规则可解释性强(如“如果天气晴且温度>25℃,则适合户外运动”);缺点:易过拟合(对训练数据中的噪声敏感)、稳定性差(数据微小变化可能导致完全不同的树结构)。类比学霸:一个学霸可能擅长数学但英语薄弱,若考试只考数学,他能拿高分;但若题目覆盖全科,总分可能不如均衡发展的学生。单棵决策树类似“偏科学霸”,在特定数据分布下表现优异,但泛化能力有限。2. 随机森林的核心理念:组队打团战随机森林通过**集成学习(Ensemble Learning)**将多棵决策树组合起来,其核心思想是:多样性:每棵树训练不同的数据子集和特征子集,避免集体“偏科”;投票制:分类问题采用多数投票,回归问题取平均值,降低个别树的错误影响。类比团队竞赛:一个团队中,成员各有短板(如有人不擅长逻辑题,有人不擅长计算题),但通过分工合作(每人负责自己擅长的部分),最终总分可能超过全能的“学霸”。二、随机森林如何“组队”?三大关键策略1. 数据采样:每棵树“刷不同的题库”随机森林采用自助采样(Bootstrap Aggregating,Bagging):从原始数据集中有放回地随机抽取n个样本,生成每个树的训练集(样本量与原始集相同,但可能有重复);未被抽中的样本(约36.8%)组成“袋外数据(OOB)”,用于评估模型性能。效果:每棵树接触的数据不同,减少过拟合风险;OOB数据提供无偏估计,无需额外划分测试集。案例:预测用户是否购买商品时,树A可能基于“年龄>30岁且点击广告”的样本训练,树B则基于“年龄≤30岁且收藏商品”的样本训练。2. 特征选择:每棵树“只看部分科目”在每个节点的分裂过程中,随机森林随机选择特征子集(而非使用所有特征):若总特征数为mmm,通常选择m\sqrt{m}m(分类问题)或m/3m/3m/3(回归问题)个特征进行分裂;通过限制特征选择范围,增加树之间的差异性。效果:避免强特征(如ID号)主导所有树的分裂,提升泛化能力;降低计算复杂度(尤其当特征维度高时)。案例:预测房价时,树A可能优先用“面积”和“卧室数”分裂,树B则用“地理位置”和“房龄”,最终综合所有树的判断。3. 投票与平均:团队的“民主决策”分类问题:每棵树独立预测类别,最终结果由多数投票决定(如100棵树中60棵预测“购买”,则输出“购买”);回归问题:取所有树预测值的平均(如预测房价时,100棵树的预测值平均后作为最终结果)。效果:单棵树的错误被其他树“纠正”,整体输出更稳定;抗噪声能力强(即使部分数据有误,不影响最终结果)。案例:在医疗诊断中,若10棵树中有8棵判断为“健康”、2棵判断为“疾病”,最终诊断为“健康”,降低误诊风险。三、随机森林的优缺点:为什么它能成为“万能工具”?优点高准确性:通过集成弱模型,显著提升预测性能(尤其在数据量较大时);抗过拟合:数据采样和特征随机性降低过拟合风险;鲁棒性强:对缺失值和噪声数据不敏感(部分树的错误被其他树抵消);并行化友好:每棵树独立训练,适合分布式计算;可解释性:通过特征重要性评分(如基尼指数下降量)理解模型决策依据。缺点计算成本高:树的数量越多,训练时间越长(但可通过限制树深度或并行化缓解);模型复杂度高:预测速度比单棵决策树慢(但通常优于深度学习模型);对类别不平衡敏感:若某类别样本极少,可能被多数类“淹没”(需通过加权或采样调整)。改进方案:使用梯度提升树(GBDT)或XGBoost,通过迭代优化残差进一步提升性能;对类别不平衡数据采用过采样(SMOTE)或欠采样。四、实战应用:随机森林能解决哪些问题?1. 分类问题场景:垃圾邮件检测、疾病诊断、客户流失预测、图像分类(辅助初筛)。案例:预测用户是否会购买商品时,随机森林可结合用户行为(点击、收藏、停留时间)和属性(年龄、性别)生成高精度预测。2. 回归问题场景:房价预测、销量预估、股票价格波动、传感器数据建模。案例:预测共享单车骑行量时,随机森林可整合天气、时间、节假日、周边设施等特征,输出更稳定的预测值。3. 特征选择场景:识别关键影响因素(如哪些特征对用户购买决策影响最大)。案例:分析电商数据时,随机森林可能发现“商品价格”比“广告曝光量”对转化率的影响更显著。4. 异常检测场景:金融欺诈识别、工业设备故障检测、网络入侵检测。案例:检测信用卡欺诈时,随机森林可通过对比正常交易与异常交易的特征分布(如交易金额、地点、时间),标记高风险行为。五、动手实践:用Python构建随机森林from sklearn.datasets import load_breast_cancer from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report import matplotlib.pyplot as plt import pandas as pd # 加载数据(乳腺癌诊断数据集) data = load_breast_cancer() X, y = data.data, data.target feature_names = data.feature_names # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 训练随机森林(100棵树,限制最大深度为5) clf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42) clf.fit(X_train, y_train) # 预测与评估 y_pred = clf.predict(X_test) print("准确率:", accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred)) # 特征重要性可视化 importances = clf.feature_importances_ features_df = pd.DataFrame({'Feature': feature_names, 'Importance': importances}) features_df = features_df.sort_values('Importance', ascending=False) plt.figure(figsize=(10, 6)) plt.barh(features_df['Feature'], features_df['Importance']) plt.xlabel('Feature Importance') plt.title('Random Forest Feature Importance') plt.show() 输出示例:准确率: 0.9649122807017544 precision recall f1-score support 0 0.97 0.94 0.95 63 1 0.96 0.98 0.97 108 accuracy 0.96 171 macro avg 0.96 0.96 0.96 171 weighted avg 0.96 0.96 0.96 171 六、结语:随机森林——AI时代的“瑞士军刀”随机森林用“多个笨模型组队”的朴素智慧,解决了单模型“偏科”和过拟合的痛点。它的成功证明:在复杂问题中,多样性比单一完美更重要。无论是工业界的快速原型开发,还是学术界的基准模型对比,随机森林都因其稳定性、易用性和高性能成为首选工具。下次当你需要构建一个“既准又稳”的模型时,不妨试试让一群“笨树”组队战斗!
-
决策树:AI如何像玩“二十问”游戏一样做判断“二十问”游戏(20 Questions)的规则很简单:一个人在心里想一个事物(如“苹果”),其他人通过最多20个“是/否”问题猜出答案。AI中的决策树(Decision Tree),正是通过类似“分步提问”的逻辑,将复杂问题拆解为一系列简单判断,最终得出结论。本文将用生活化案例拆解决策树的工作原理,并介绍其优缺点与实战应用。一、决策树:AI的“二十问”游戏规则什么是决策树?决策树是一种监督学习算法,通过模拟人类“分步决策”的逻辑,从数据中学习判断规则。它的结构像一棵倒置的树:根节点:问题的起点(如“天气是晴天吗?”);内部节点:中间判断条件(如“温度>25℃?”);叶节点:最终结论(如“适合户外运动”)。类比“二十问”游戏:目标:猜出用户心中的事物(如“动物”“水果”);策略:每次提问缩小范围(如“是哺乳动物吗?”→“能飞吗?”);终止条件:足够确定答案或达到问题上限。决策树的训练过程,就是从数据中自动生成最优提问序列的过程。二、决策树如何“提问”?三大核心步骤1. 选择最佳“提问”特征决策树通过特征选择决定每个节点的判断条件,目标是让每次提问后,子节点的“纯度”最高(即同类样本尽可能集中)。常用方法:信息增益(ID3算法):选择能最大程度减少信息不确定性的特征。公式:IG(Y,X)=H(Y)−H(Y∣X)IG(Y,X) = H(Y) - H(Y|X)IG(Y,X)=H(Y)−H(Y∣X)H(Y)H(Y)H(Y):原始数据的信息熵(混乱程度);H(Y∣X)H(Y|X)H(Y∣X):按特征XXX分割后的条件熵。基尼指数(CART算法):衡量样本被错误分类的概率,选择基尼指数最小的特征。公式:Gini(D)=1−∑k=1Kpk2Gini(D) = 1 - \sum_{k=1}^{K}p_k^2Gini(D)=1−∑k=1Kpk2pkp_kpk:第kkk类样本的比例。案例:预测“是否适合户外运动”,数据包含天气、温度、风力等特征。决策树可能优先选择“天气是晴天吗?”,因为晴天时户外运动的概率更高(信息增益最大)。2. 递归分裂:构建树结构决策树通过递归分裂生成子节点:从根节点开始,根据最佳特征分割数据;对每个子节点重复步骤1,直到满足停止条件(如样本纯度足够高或达到最大深度);最终所有叶节点给出分类或回归结果。类比“二十问”:第一问:“是动物吗?”→ 分裂为“动物”和“非动物”两组;对“动物”组继续问:“是哺乳动物吗?”→ 进一步分裂;直到足够确定答案(如“是猫”)。3. 剪枝:避免“过度提问”决策树容易过拟合(如生成过深的树,记住训练数据中的噪声)。**剪枝(Pruning)**通过移除冗余节点简化树结构:预剪枝:提前限制树深度、最小样本数等;后剪枝:先生成完整树,再自底向上删除对性能影响小的节点。案例:若训练数据中有一例“雨天但适合户外运动”(因特殊活动),决策树可能生成“天气=雨天且温度>30℃”的冗余规则。剪枝可忽略此类极端情况,提升泛化能力。三、决策树的优缺点:简单但易“钻牛角尖”优点直观易懂:规则可解释性强(如“如果天气晴且温度>25℃,则适合户外运动”);处理混合数据:支持数值型(温度)和类别型(天气)特征;无需数据标准化:对特征尺度不敏感(如温度单位℃或℉不影响结果);快速训练与预测:适合小规模数据或实时决策场景。缺点易过拟合:复杂树可能记住噪声数据(如“雨天+温度=25.5℃+风力=3级时适合运动”);不稳定:数据微小变化可能导致树结构剧烈变化(如删除一个样本可能改变根节点特征);偏向高基数特征:若某特征取值多(如ID号),可能被优先选择(但无实际意义)。改进方案:使用随机森林(Random Forest)或梯度提升树(GBDT),通过集成多棵树降低过拟合风险;限制树深度、设置最小样本分裂数等预剪枝参数。四、实战应用:决策树能解决哪些问题?1. 分类问题场景:邮件分类(垃圾/正常)、疾病诊断(感冒/流感)、客户分群(高价值/低价值)。案例:根据症状(发烧、咳嗽、头痛)预测疾病,决策树可能生成规则:若“发烧=是”且“咳嗽=是”→ 流感;若“发烧=否”且“头痛=是”→ 偏头痛。2. 回归问题场景:房价预测、销量预估、年龄估计。案例:根据房屋面积、卧室数、地理位置预测房价,决策树可能生成规则:若“面积>100㎡”且“卧室数≥3”→ 房价>500万;否则→ 房价≤500万。3. 特征选择场景:识别关键影响因素(如哪些特征对用户购买决策影响最大)。案例:分析用户点击广告的行为,决策树可能发现“广告位置=首页”比“颜色=红色”更重要。五、动手实践:用Python构建决策树from sklearn.datasets import load_iris from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree import matplotlib.pyplot as plt # 加载数据 data = load_iris() X, y = data.data, data.target # 训练决策树(限制深度为3避免过拟合) clf = DecisionTreeClassifier(max_depth=3, criterion='gini') clf.fit(X, y) # 输出规则 tree_rules = export_text(clf, feature_names=data.feature_names) print("决策树规则:\n", tree_rules) # 可视化 plt.figure(figsize=(12, 8)) plot_tree(clf, feature_names=data.feature_names, class_names=data.target_names, filled=True) plt.show() 输出示例:决策树规则: |--- petal width (cm) <= 0.80\n | class: setosa\n|--- petal width (cm) > 0.80\n |--- petal width (cm) <= 1.75\n | |--- petal length (cm) <= 5.35\n | | class: versicolor\n | |--- petal length (cm) > 5.35\n | | class: virginica\n |--- petal width (cm) > 1.75\n | class: virginica六、结语:决策树——AI的“逻辑推理小白”决策树像一位擅长“二十问”游戏的AI新手,通过分步提问逐步逼近答案。它的简单性使其成为理解机器学习逻辑的入门工具,但局限性也催生了更强大的集成方法(如随机森林)。下次当你需要解释一个AI决策时,不妨想想:如果用决策树模拟它的逻辑,会生成怎样的“提问链”?
-
损失函数:AI的“错题本”如何指导它进步考试后,老师会让我们整理错题本,分析每道题的错误原因,避免下次再犯。在AI训练中,也有一个类似的“错题本”——损失函数(Loss Function)。它不仅记录模型的“错误”,还通过量化错误程度,指导模型调整参数、逐步优化。本文将用生活化案例拆解损失函数的作用机制,并介绍几种常见类型。一、损失函数:AI的“错误评分系统”什么是损失函数?损失函数是AI模型训练的核心工具,它的作用是:计算预测值与真实值的差距(即“错误程度”);将错误转化为可优化的数值(损失值);通过最小化损失值,驱动模型参数更新。类比错题本:错题记录:模型每次预测错误的数据点(如把猫误判为狗);错误分析:损失函数计算错误的严重性(如“猫狗误判”比“猫虎误判”损失更小);改进方向:根据损失值调整模型参数,减少同类错误。二、损失函数如何指导AI进步?1. 量化错误:从“差不多”到“精确打击”假设训练一个图像分类模型,输入一张猫的图片,模型输出预测概率:真实标签:猫(概率应为100%)模型预测:猫(80%)、狗(15%)、老虎(5%)损失函数的作用:计算预测与真实的差距(如交叉熵损失会惩罚低概率的正确类别);生成一个具体的损失值(如0.5),数值越小表示模型越准确。类比学习:学生答题后,老师不会只说“错了”,而是会扣分(如选择题错一题扣2分);损失函数通过数值量化错误,让模型明确“改进空间有多大”。2. 反向传播:根据错误调整参数模型通过反向传播算法(Backpropagation)利用损失函数更新参数:计算损失值对每个参数的梯度(即“参数调整方向”);沿梯度反方向调整参数(如减少导致错误增大的权重);重复迭代,逐步降低损失值。类比纠错:学生根据错题本分析错误原因(如“公式记错”);针对性复习公式(调整参数),避免下次再犯。三、常见损失函数类型与适用场景1. 均方误差(MSE,Mean Squared Error)公式:MSE=1n∑i=1n(yi−y^i)2MSE = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 MSE=n1i=1∑n(yi−y^i)2特点:对大错误惩罚更重(误差平方后放大);适用于回归问题(如预测房价、温度)。案例:预测房价时,若真实值为300万,模型预测为200万,误差为100万,MSE会将其放大为1亿,迫使模型重点关注大误差。2. 交叉熵损失(Cross-Entropy Loss)公式(二分类):L=−[ylog(y^)+(1−y)log(1−y^)]L = -[y \log(\hat{y}) + (1-y)\log(1-\hat{y})] L=−[ylog(y^)+(1−y)log(1−y^)]特点:惩罚预测概率与真实标签的偏离(如真实为猫,但模型预测概率低);适用于分类问题(如图像分类、文本情感分析)。案例:将猫误判为狗时,若模型对猫的预测概率仅为0.3(真实应为1),交叉熵损失会生成一个较大的值(约1.2),驱动模型提高猫类别的概率。3. 平均绝对误差(MAE,Mean Absolute Error)公式:MAE=1n∑i=1n∣yi−y^i∣MAE = \frac{1}{n}\sum_{i=1}^{n}|y_i - \hat{y}_i| MAE=n1i=1∑n∣yi−y^i∣特点:对所有错误一视同仁(误差线性计算);适用于对异常值不敏感的场景(如预测销量,偶尔的极端值不影响整体)。对比MSE:MSE对异常值更敏感(误差平方后放大);MAE更鲁棒,但梯度恒定(可能导致收敛变慢)。4. Hinge Loss(合页损失)公式(支持向量机SVM):L=max(0,1−y⋅y^)L = \max(0, 1 - y \cdot \hat{y}) L=max(0,1−y⋅y^)特点:关注分类边界的“安全距离”(希望正确类别的预测值远大于其他类);适用于二分类问题(如垃圾邮件检测)。案例:若真实标签为1(正类),模型预测值为0.8,Hinge Loss为0(满足安全距离);若预测值为0.5,损失为0.5,驱动模型提高预测值。四、如何选择损失函数?任务类型推荐损失函数选择理由回归(预测连续值)MSE、MAE直接量化数值差异分类(多类别)交叉熵损失惩罚概率分布偏离二分类交叉熵、Hinge Loss交叉熵通用,Hinge Loss适合SVM异常检测MAE或自定义损失减少异常值干扰实战技巧:从任务目标出发:若需严格惩罚大错误(如医疗诊断),选MSE;若需鲁棒性(如金融风控),选MAE。尝试组合损失:如目标检测中同时使用分类损失和定位损失(如Smooth L1 Loss)。监控损失曲线:若训练集损失下降但验证集损失上升,可能过拟合,需调整模型或正则化。五、结语:损失函数——AI的“纠错老师”损失函数是AI模型的“错题本”和“评分系统”,它通过量化错误、指导参数更新,让模型从“懵懂无知”逐步成长为“精准预测”。理解不同损失函数的特性,能帮助我们根据任务需求选择合适的工具,就像学生根据科目特点选择复习方法一样。下次训练模型时,不妨想想:如果它是你的学生,你会为它设计怎样的“错题本”?
-
过拟合与欠拟合:AI模型也会“学过头”和“学不会”?在AI训练过程中,我们常遇到两种尴尬情况:模型在训练数据上表现完美,一到新数据就“翻车”(过拟合);或者连训练数据都学不明白,像极了考试总不及格的学生(欠拟合)。这两种现象就像走钢丝——平衡“学得够”和“学得巧”是模型性能的关键。本文用生活化案例带你轻松理解这两个核心概念。一、过拟合:当AI变成“死记硬背”的学霸现象:模型在训练集上准确率99%,测试集上却只有60%,像极了考试前背熟所有例题,换个问法就答错的学生。为什么会出现过拟合?数据量太少:假设用5张猫狗照片训练模型,它可能记住每张照片的背景颜色(如“绿色背景=猫”),而非真正的猫狗特征。类比:只见过5种水果的孩子,可能认为“圆形+红色=苹果”,但遇到草莓或樱桃就会混淆。模型太复杂:用100层神经网络拟合简单的线性数据(如身高与年龄的关系),模型会“创造”出不必要的复杂曲线来完美穿过每个训练点。类比:用高等数学解小学算术题,反而容易算错。训练时间过长:模型反复“啃”训练数据,连数据中的噪声(如照片模糊、标注错误)都当成了规律。类比:背单词时把例句中的错别字也记了下来。如何解决过拟合?简化模型:减少神经网络层数或决策树深度。增加数据:用更多样化的数据训练(如更多猫狗品种、不同角度的照片)。正则化:给模型“减肥”,限制参数值大小(如L1/L2正则化)。早停法:在验证集性能下降时提前终止训练。交叉验证:用不同数据子集多次训练,避免对特定数据“偏科”。二、欠拟合:当AI变成“一知半解”的学渣现象:模型在训练集和测试集上表现都很差,像极了连课本例题都解不出的学生。为什么会出现欠拟合?模型太简单:用直线拟合“正弦曲线”数据,无论怎么调整参数都无法拟合波动。类比:用算盘计算微积分,工具本身能力不足。特征不足:预测房价时只考虑面积,忽略了楼层、地段等关键因素。类比:判断水果甜度只看颜色,忽略了品种和成熟度。数据问题:数据存在大量缺失值或错误标注,导致模型无法学习有效规律。类比:课本印刷错误百出,学生越学越糊涂。如何解决欠拟合?增加模型复杂度:改用深度神经网络或增加决策树深度。丰富特征:加入更多相关特征(如房价预测中加入学区、交通等维度)。减少正则化:如果使用了正则化,尝试降低其强度。检查数据质量:修复缺失值、修正错误标注、处理异常值。三、过拟合 vs 欠拟合:如何找到平衡点?对比项过拟合欠拟合训练集表现准确率极高(接近100%)准确率低测试集表现准确率显著下降准确率同样低模型复杂度过高(参数过多/层数过深)过低(参数过少/层数过浅)典型场景数据量少、模型复杂、训练时间长数据特征不足、模型过于简单解决方案简化模型、增加数据、正则化增加复杂度、丰富特征、优化数据实战技巧:绘制学习曲线:观察训练集和验证集准确率随训练轮次的变化,若两者差距持续扩大,可能过拟合;若两者同步低迷,可能欠拟合。网格搜索调参:通过交叉验证尝试不同模型复杂度(如决策树深度),找到性能最佳点。结语:AI训练的“中庸之道”过拟合和欠拟合的本质是模型与数据的“匹配度”问题:前者像“过度解读”,后者像“理解不足”。作为开发者,我们需要像调音响音量一样,通过调整模型复杂度、数据量和特征工程,找到那个“刚刚好”的平衡点。记住:好的模型不是完美拟合训练数据,而是能在新场景中稳健预测——这或许就是AI学习的“中庸之道”。
-
人类语言是地球上最复杂的符号系统之一,它承载着抽象概念、情感表达和文化传承。然而,计算机作为基于二进制逻辑的机器,如何“理解”这种充满模糊性和语境依赖的自然语言?这一过程经历了从简单规则匹配到深度神经网络的革命性演变,本文将带您揭开自然语言处理(NLP)的技术面纱。一、早期尝试:基于规则的“机械翻译”20世纪50年代,计算机科学家们试图通过硬编码语法规则实现机器翻译。例如,早期的系统会将句子拆解为词性标签(名词、动词等),再根据预设的语法结构重组目标语言。这种方法在简单句子上表现尚可,但面对人类语言的歧义性时迅速崩溃:词汇歧义:英文单词“bank”既可指“银行”也可指“河岸”;句法歧义:“Flying planes can be dangerous”既可理解为“驾驶飞机很危险”,也可指“飞行的飞机本身很危险”;语义依赖:“把书放在桌子上”中的“桌子”是“放”的受事对象,而计算机难以捕捉这种关系。这种“符号主义”方法本质上是将人类语言简化为逻辑推理问题,但自然语言的非形式化特性使其注定失败。二、统计革命:让计算机从数据中学习1990年代,统计方法开始主导NLP领域。核心思想是:语言规律隐藏在海量文本中,计算机可以通过概率统计“发现”模式。典型技术包括:N-gram模型:通过统计连续N个词出现的频率预测下一个词(如“我爱你”后接“吗”的概率高于“你爱我”);词向量(Word Embedding):将单词映射为高维空间中的向量,使语义相似的词在向量空间中距离更近(如“猫”和“狗”的向量夹角小于“猫”和“火箭”);隐马尔可夫模型(HMM):用于分词、词性标注等任务,通过观察序列推断隐藏状态。这一阶段的技术突破使机器翻译质量显著提升,但仍依赖人工特征工程,且无法处理长距离语义依赖(如否定词“不”对句子整体的影响)。三、深度学习时代:神经网络的“语言直觉”2010年后,深度学习彻底改变了NLP格局。其核心优势在于:通过端到端训练自动学习语言特征,无需人工设计规则。关键技术包括:循环神经网络(RNN):通过循环结构处理序列数据,捕捉上下文信息(如理解“他”指代前文的“张三”);注意力机制(Attention):动态聚焦关键信息(如翻译“苹果公司”时重点关注“苹果”而非无关词汇);Transformer架构:通过自注意力机制并行处理整个句子,使模型能够“全局思考”(如GPT系列模型通过预测下一个词学习语言模式)。现代大模型(如GPT-4、文心一言)已能生成连贯文本、回答复杂问题,甚至进行创意写作。其“理解”本质是在海量数据中建立统计关联,但这种“理解”与人类仍有本质差异:模型缺乏真实语义和常识推理能力,更多是“概率押注”。四、未来挑战:从“理解”到“共情”尽管技术进步显著,但计算机理解人类语言仍面临挑战:隐喻与讽刺:如何识别“这天气真暖和”(字面)与“这天气冷得像冰箱”(讽刺)的区别?文化语境:中文“龙”象征吉祥,而西方“dragon”代表邪恶,模型需理解文化符号差异;情感分析:判断“这部电影还行”是褒义还是贬义,需结合语气和上下文。未来的方向可能包括:多模态融合:结合图像、语音等模态增强理解(如通过表情判断讽刺);常识推理:引入知识图谱补充世界知识;可解释性:让模型解释决策过程(如“为什么认为这句话是积极的?”)。
-
智能体目标冲突解决多目标优化中的权重动态调整策略在真实业务或自主决策型 Agent 系统中,智能体往往并非只追求单一目标。例如:无人机需要兼顾任务收益、能源消耗、安全风险;推荐系统需要平衡用户体验、商业转化、内容多样性;智能客服需要同时满足响应速度、答案准确度、用户情绪稳定性。这些目标之间往往存在天然冲突,导致无法单纯依赖固定的权重体系来求解最优策略。我个人认为,多目标优化的难点不在于目标数量的增加,而在于权衡关系的动态性和上下文依赖性。因此,本篇文章讨论的是一种更贴近实际工程的解决方法:动态权重调整策略(Dynamic Weight Adjustment, DWA)。一、为什么固定权重不可行?传统多目标方法通常采用线性加权方式:总目标 = w1 * A + w2 * B + w3 * C但在真实系统中可能出现以下问题:场景变化快:用户状态、环境信息、风险等级随时变化,固定权重无法适配。目标间存在阶段性主次关系:如节能优先还是性能优先取决于电量是否充足。实时反馈信息必须进入优化循环:策略效果应该影响下一轮权重,而不是独立存在。换句话说,智能体真正需要的不是一个公式,而是动态博弈式权衡机制。二、动态权重调整的常用策略(工程实践视角)我把它总结为以下三类,可独立使用或混合使用:策略类型核心思路适用场景性能变化驱动根据每轮目标达成率调整权重训练/迭代型智能体(RL、AutoML)环境与状态驱动根据上下文环境动态切换权重真实物理环境或实时系统用户或业务策略驱动根据 KPI 和 SLA 自动调整企业级平台与推荐系统在实际落地中,我比较推荐状态驱动 + 性能驱动的混合方案,既兼顾系统稳定性,又能具备自适应能力。三、基于性能反馈的动态权重示例思路:每一轮优化后,如果某个目标表现不佳,则适当提升其权重;反之降低。实战代码示例(Python)以下示例使用一个简单任务:智能体需要同时最小化时间消耗和成本支出,并对权重进行动态反馈调整。import random class MultiObjectiveAgent: def __init__(self, w_time=0.5, w_cost=0.5, lr=0.1): self.weights = {"time": w_time, "cost": w_cost} self.lr = lr def evaluate(self): # 模拟性能结果(越小越好) result = { "time": random.uniform(0.1, 1.0), "cost": random.uniform(0.1, 1.0) } return result def adjust_weights(self, result): total = sum(result.values()) normalized = {k: v / total for k, v in result.items()} # 根据表现动态调整(表现越差权重越高) for k in self.weights: adjustment = self.lr * normalized[k] self.weights[k] += adjustment # 归一化 total_w = sum(self.weights.values()) for k in self.weights: self.weights[k] /= total_w def run(self, rounds=10): for step in range(rounds): result = self.evaluate() self.adjust_weights(result) print(f"Step {step+1}") print(f" Performance: {result}") print(f" Adjusted Weights: {self.weights}") print("-"*40) if __name__ == "__main__": agent = MultiObjectiveAgent() agent.run(10) 输出分析思路当某个目标表现持续较差时,其权重会逐渐提高,促使智能体系统在下一轮更倾向于优化此目标,从而形成自适应的目标平衡机制。虽然示例为简化模型,但和企业级调参逻辑一致:用反馈信息驱动资源配置优先级变动。四、工程化落地的思考与建议我在经验中发现,动态权重策略在实际项目部署时需要注意以下几点:不要过度追求实时性权重每次变化过大可能导致智能体策略震荡,可增加滑动平均或模糊逻辑。可以设置硬约束区间一些安全性目标不能被下降到过低,可以设最小阈值。考虑用户感知权重,而非纯数学最优用户体验是非线性的,稍微偏差也可能导致满意度骤降。权重可以成为模型训练的超参数,而非固定参数把它当作学习目标的一部分,而不是外部设定值。五、动态权重策略的系统化设计框架(从策略走向架构)如果把动态权重调整看作一个功能点,往往只停留在代码层面;但如果把它视作智能体核心决策模块之一,我们需要构建更完整的架构。我的经验是,可以将其抽象为四层结构:┌──────────────────────┐ │ 4. 策略执行层 (Policy Layer) │ ← 基于动态权重输出最终策略 ├──────────────────────┤ │ 3. 评估反馈层 (Evaluation Layer) │ ← 收集任务表现、环境状态、风险指数 ├──────────────────────┤ │ 2. 权重调控层 (Weight Adaptation) │ ← 动态调整并归一化权重 ├──────────────────────┤ │ 1. 目标定义层 (Objective Layer) │ ← 明确目标、约束与优先级底线 └──────────────────────┘这个框架能确保系统不是“凭感觉地调权重”,而是有输入、有计算、有反馈、有验证的闭环结构。推荐的工程化实践规则规则含义实践建议R1所有目标必须可指标化转化为可测量、可量化结果值R2权重变化必须可解释保存变更日志用于审计分析R3调整不超过安全区间避免短期波动导致策略漂移R4权重 ≠ 优先级可再引入元优先级做兜底尤其是 R4,这是许多人忽视的 —— 两个目标权重相同,不代表优先级相同,比如安全永远高于收益。六、引入环境驱动的权重切换机制(状态机建模)在许多实时系统中,权重不仅需要动态变化,还要根据状态进行阶段性切换。一种有效方法是将其设计成有限状态机(Finite State Machine, FSM)。示例:无人机任务状态权重模型状态描述主目标次级目标权重策略起飞阶段系统初始上升安全稳定性安全最大化任务巡航执行路径规划能耗 / 时间稳定性反馈驱动动态权重电量告警< 30% 电量能源安全返回能耗权重急速上升紧急状况风险触发安全其他全部放弃强制切换策略这种结合状态机的动态权重策略,本质上是让系统从“自动拟合”进化到自主决策策略切换”。状态驱动代码class WeightManager: def __init__(self): self.weights = {"safety": 0.4, "efficiency": 0.4, "energy": 0.2} def update_state(self, battery, risk): if risk > 0.7: return "emergency" if battery < 0.3: return "low_power" return "normal" def adjust_by_state(self, state): if state == "emergency": self.weights = {"safety": 1.0, "efficiency": 0.0, "energy": 0.0} elif state == "low_power": self.weights = {"safety": 0.3, "efficiency": 0.1, "energy": 0.6} else: # normal pass # 沿用动态调整权重流程 return self.weights核心思想:动态策略 ≠ 全局连续变化,而是分阶段精准控制。七、如何为动态权重引入“学习能力”:元策略思想目前很多动态权重方案依然是手动规则 + 简单反馈,未真正智能化。更进一步的方向是引入Meta-Policy(元策略),让权重不仅影响智能体行为,还能被学习、被优化。可能的学习机制包括:强化学习(RL)驱动的权重自适应基于奖励差异的反向调节机制使用策略梯度更新权重区间利用历史轨迹拟合权重演变模型Python 简易元学习代码history = [] def meta_update(weights, performance): history.append((weights.copy(), performance)) if len(history) > 5: recent = history[-5:] trend = sum([p["reward"] for _, p in recent]) / 5 if trend < benchmark: # 自动提升探索性 for k in weights: weights[k] += random.uniform(-0.05, 0.05) # 归一化 total = sum(weights.values()) for k in weights: weights[k] /= total return weights这段逻辑虽然简化,但体现了核心思想:不仅优化目标,更优化目标之间的关系。八、从单体智能体到协同智能体(Multi-Agent)在分布式智能体系统中,不同Agent之间可能目标不同,甚至互斥,例如:能源调度系统:发电方与调度方目标冲突联盟推荐系统:商业方与用户方指标冲突机器人协同:局部最优与全局最优冲突此时,动态权重不仅作用于单体智能体,还可能上升为群体协商协议,可采用:方法核心思想工程价值博弈论均衡点决策严谨但复杂协同 RL学习群体最优策略自适应性强共识协议限定可接受区间工程成本低总结在智能体从“执行式自动化”向“自主性决策体”演进的过程中,多目标冲突是绕不过的核心挑战。真正的难点并不是目标数量、优化方法或计算能力,而是如何让智能体在动态环境中持续保持合理的目标平衡感,并具备自适应调整能力。本文所讨论的动态权重策略,本质是一种面向现实复杂性的工程思路:不再把目标关系视为静态参数,而是让系统具备“权衡-反馈-再平衡”的智能循环机制。通过性能反馈、环境状态、策略阶段与元学习,将权重从配置项提升为可学习、可解释且可演化的决策变量,让智能体的行为更像一个成熟决策者,而不是被动执行器。我个人认为,这一方向的最终落点不会停留在权重本身,而是指向以下三个未来能力:目标理解能力(Goal Reasoning)智能体不仅知道要做什么,还能判断“什么时候该重视什么”。策略弹性能力(Policy Adaptiveness)面对变化不是“固守”,而是“策略性调整”。价值观一致性(Value Alignment)在复杂目标下坚持底线原则与长期目标,而非短期最优。当智能体能自洽地处理目标冲突,它才真正迈向具备智能性、稳健性与可信度的下一层级。
-
Ascend310部署Qwen-VL-7B实现吸烟动作识别OrangePi AI Studio Pro是基于2个昇腾310P处理器的新一代高性能推理解析卡,提供基础通用算力+超强AI算力,整合了训练和推理的全部底层软件栈,实现训推一体。其中AI半精度FP16算力约为176TFLOPS,整数Int8精度可达352TOPS,本文将带领大家在Ascend 310P上部署Qwen2.5-VL-7B多模态理解大模型实现吸烟动作的识别。一、环境配置我们在OrangePi AI Stuido上使用Docker容器部署MindIE:docker pull swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.1.RC1-300I-Duo-py311-openeuler24.03-ltsroot@orangepi:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie 2.1.RC1-300I-Duo-py311-openeuler24.03-lts 0574b8d4403f 3 months ago 20.4GB langgenius/dify-web 1.0.1 b2b7363571c2 8 months ago 475MB langgenius/dify-api 1.0.1 3dd892f50a2d 8 months ago 2.14GB langgenius/dify-plugin-daemon 0.0.4-local 3f180f39bfbe 8 months ago 1.35GB ubuntu/squid latest dae40da440fe 8 months ago 243MB postgres 15-alpine afbf3abf6aeb 8 months ago 273MB nginx latest b52e0b094bc0 9 months ago 192MB swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie 1.0.0-300I-Duo-py311-openeuler24.03-lts 74a5b9615370 10 months ago 17.5GB redis 6-alpine 6dd588768b9b 10 months ago 30.2MB langgenius/dify-sandbox 0.2.10 4328059557e8 13 months ago 567MB semitechnologies/weaviate 1.19.0 8ec9f084ab23 2 years ago 52.5MB之后创建一个名为start-docker.sh的启动脚本,内容如下:NAME=$1 if [ $# -ne 1 ]; then echo "warning: need input container name.Use default: mindie" NAME=mindie fi docker run --name ${NAME} -it -d --net=host --shm-size=500g \ --privileged=true \ -w /usr/local/Ascend/atb-models \ --device=/dev/davinci_manager \ --device=/dev/hisi_hdc \ --device=/dev/devmm_svm \ --entrypoint=bash \ -v /models:/models \ -v /data:/data \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ -v /usr/local/dcmi:/usr/local/dcmi \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ -v /usr/local/sbin:/usr/local/sbin \ -v /home:/home \ -v /tmp:/tmp \ -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \ -e http_proxy=$http_proxy \ -e https_proxy=$https_proxy \ -e "PATH=/usr/local/python3.11.6/bin:$PATH" \ swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.1.RC1-300I-Duo-py311-openeuler24.03-ltsbash start-docker.sh启动容器后,我们需要替换几个文件并安装Ascend-cann-nnal软件包:root@orangepi:~# docker exec -it mindie bash Welcome to 5.15.0-126-generic System information as of time: Sat Nov 15 22:06:48 CST 2025 System load: 1.87 Memory used: 6.3% Swap used: 0.0% Usage On: 33% Users online: 0 [root@orangepi atb-models]# cd /usr/local/Ascend/ascend-toolkit/8.2.RC1/lib64/ [root@orangepi lib64]# ls /data/fix_openeuler_docker/fixhccl/8.2hccl/ libhccl.so libhccl_alg.so libhccl_heterog.so libhccl_plf.so [root@orangepi lib64]# cp /data/fix_openeuler_docker/fixhccl/8.2hccl/* ./ cp: overwrite './libhccl.so'? cp: overwrite './libhccl_alg.so'? cp: overwrite './libhccl_heterog.so'? cp: overwrite './libhccl_plf.so'? [root@orangepi lib64]# source /usr/local/Ascend/ascend-toolkit/set_env.sh [root@orangepi lib64]# chmod +x /data/fix_openeuler_docker/Ascend-cann-nnal/Ascend-cann-nnal_8.3.RC1_linux-x86_64.run [root@orangepi lib64]# /data/fix_openeuler_docker/Ascend-cann-nnal/Ascend-cann-nnal_8.3.RC1_linux-x86_64.run --install --quiet [NNAL] [20251115-22:41:45] [INFO] LogFile:/var/log/ascend_seclog/ascend_nnal_install.log [NNAL] [20251115-22:41:45] [INFO] Ascend-cann-atb_8.3.RC1_linux-x86_64.run --install --install-path=/usr/local/Ascend/nnal --install-for-all --quiet --nox11 start WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv [NNAL] [20251115-22:41:58] [INFO] Ascend-cann-atb_8.3.RC1_linux-x86_64.run --install --install-path=/usr/local/Ascend/nnal --install-for-all --quiet --nox11 install success [NNAL] [20251115-22:41:58] [INFO] Ascend-cann-SIP_8.3.RC1_linux-x86_64.run --install --install-path=/usr/local/Ascend/nnal --install-for-all --quiet --nox11 start [NNAL] [20251115-22:41:59] [INFO] Ascend-cann-SIP_8.3.RC1_linux-x86_64.run --install --install-path=/usr/local/Ascend/nnal --install-for-all --quiet --nox11 install success [NNAL] [20251115-22:41:59] [INFO] Ascend-cann-nnal_8.3.RC1_linux-x86_64.run install success Warning!!! If the environment variables of atb and asdsip are set at the same time, unexpected consequences will occur. Import the corresponding environment variables based on the usage scenarios: atb for large model scenarios, asdsip for embedded scenarios. Please make sure that the environment variables have been configured. If you want to use atb module: - To take effect for current user, you can exec command below: source /usr/local/Ascend/nnal/atb/set_env.sh or add "source /usr/local/Ascend/nnal/atb/set_env.sh" to ~/.bashrc. If you want to use asdsip module: - To take effect for current user, you can exec command below: source /usr/local/Ascend/nnal/asdsip/set_env.sh or add "source /usr/local/Ascend/nnal/asdsip/set_env.sh" to ~/.bashrc. [root@orangepi lib64]# cat /usr/local/Ascend/nnal/atb/latest/version.info Ascend-cann-atb : 8.3.RC1 Ascend-cann-atb Version : 8.3.RC1.B106 Platform : x86_64 branch : 8.3.rc1-0702 commit id : 16004f23040e0dcdd3cf0c64ecf36622487038ba修改推理使用的逻辑NPU核心为0,1,测试多模态理解大模型:Qwen2.5-VL-7B-Instruct:运行结果表明,Qwen2.5-VL-7B-Instruct在2 x Ascned 310P上推理平均每秒可以输出20个tokens,同时准确理解画面中的人物信息和行为动作。[root@orangepi atb-models]# bash examples/models/qwen2_vl/run_pa.sh --model_path /models/Qwen2.5-VL-7B-Instruct/ --input_image /root/pic/test.jpg [2025-11-15 22:12:49,663] torch.distributed.run: [WARNING] [2025-11-15 22:12:49,663] torch.distributed.run: [WARNING] ***************************************** [2025-11-15 22:12:49,663] torch.distributed.run: [WARNING] Setting OMP_NUM_THREADS environment variable for each process to be 1 in default, to avoid your system being overloaded, please further tune the variable for optimal performance in your application as needed. [2025-11-15 22:12:49,663] torch.distributed.run: [WARNING] ***************************************** /usr/local/lib64/python3.11/site-packages/torchvision/io/image.py:13: UserWarning: Failed to load image Python extension: 'libc10_cuda.so: cannot open shared object file: No such file or directory'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source? warn( /usr/local/lib64/python3.11/site-packages/torchvision/io/image.py:13: UserWarning: Failed to load image Python extension: 'libc10_cuda.so: cannot open shared object file: No such file or directory'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source? warn( 2025-11-15 22:12:53.250 7934 LLM log default format: [yyyy-mm-dd hh:mm:ss.uuuuuu] [processid] [threadid] [llmmodels] [loglevel] [file:line] [status code] msg 2025-11-15 22:12:53.250 7933 LLM log default format: [yyyy-mm-dd hh:mm:ss.uuuuuu] [processid] [threadid] [llmmodels] [loglevel] [file:line] [status code] msg [2025-11-15 22:12:53.250] [7934] [139886327420160] [llmmodels] [WARN] [model_factory.cpp:28] deepseekV2_DecoderModel model already exists, but the duplication doesn't matter. [2025-11-15 22:12:53.250] [7933] [139649439929600] [llmmodels] [WARN] [model_factory.cpp:28] deepseekV2_DecoderModel model already exists, but the duplication doesn't matter. [2025-11-15 22:12:53.250] [7934] [139886327420160] [llmmodels] [WARN] [model_factory.cpp:28] deepseekV2_DecoderModel model already exists, but the duplication doesn't matter. [2025-11-15 22:12:53.250] [7933] [139649439929600] [llmmodels] [WARN] [model_factory.cpp:28] deepseekV2_DecoderModel model already exists, but the duplication doesn't matter. [2025-11-15 22:12:53.250] [7934] [139886327420160] [llmmodels] [WARN] [model_factory.cpp:28] llama_LlamaDecoderModel model already exists, but the duplication doesn't matter. [2025-11-15 22:12:53.250] [7933] [139649439929600] [llmmodels] [WARN] [model_factory.cpp:28] llama_LlamaDecoderModel model already exists, but the duplication doesn't matter. [2025-11-15 22:12:55,335] [7934] [139886327420160] [llmmodels] [INFO] [cpu_binding.py-254] : rank_id: 1, device_id: 1, numa_id: 0, shard_devices: [0, 1], cpus: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] [2025-11-15 22:12:55,336] [7934] [139886327420160] [llmmodels] [INFO] [cpu_binding.py-280] : process 7934, new_affinity is [8, 9, 10, 11, 12, 13, 14, 15], cpu count 8 [2025-11-15 22:12:55,356] [7933] [139649439929600] [llmmodels] [INFO] [cpu_binding.py-254] : rank_id: 0, device_id: 0, numa_id: 0, shard_devices: [0, 1], cpus: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] [2025-11-15 22:12:55,357] [7933] [139649439929600] [llmmodels] [INFO] [cpu_binding.py-280] : process 7933, new_affinity is [0, 1, 2, 3, 4, 5, 6, 7], cpu count 8 [2025-11-15 22:12:56,032] [7933] [139649439929600] [llmmodels] [INFO] [model_runner.py-156] : model_runner.quantize: None, model_runner.kv_quant_type: None, model_runner.fa_quant_type: None, model_runner.dtype: torch.float16 [2025-11-15 22:13:01,826] [7933] [139649439929600] [llmmodels] [INFO] [dist.py-81] : initialize_distributed has been Set [2025-11-15 22:13:01,827] [7933] [139649439929600] [llmmodels] [INFO] [model_runner.py-187] : init tokenizer done Using a slow image processor as `use_fast` is unset and a slow processor was saved with this model. `use_fast=True` will be the default behavior in v4.48, even if the model was saved with a slow processor. This will result in minor differences in outputs. You'll still be able to use a slow processor with `use_fast=False`. [2025-11-15 22:13:02,070] [7934] [139886327420160] [llmmodels] [INFO] [dist.py-81] : initialize_distributed has been Set Using a slow image processor as `use_fast` is unset and a slow processor was saved with this model. `use_fast=True` will be the default behavior in v4.48, even if the model was saved with a slow processor. This will result in minor differences in outputs. You'll still be able to use a slow processor with `use_fast=False`. [W InferFormat.cpp:62] Warning: Cannot create tensor with NZ format while dim < 2, tensor will be created with ND format. (function operator()) [W InferFormat.cpp:62] Warning: Cannot create tensor with NZ format while dim < 2, tensor will be created with ND format. (function operator()) [2025-11-15 22:13:08,435] [7933] [139649439929600] [llmmodels] [INFO] [flash_causal_qwen2.py-153] : >>>> qwen_QwenDecoderModel is called. [2025-11-15 22:13:08,526] [7934] [139886327420160] [llmmodels] [INFO] [flash_causal_qwen2.py-153] : >>>> qwen_QwenDecoderModel is called. [2025-11-15 22:13:16.666] [7933] [139649439929600] [llmmodels] [WARN] [operation_factory.cpp:42] OperationName: TransdataOperation not find in operation factory map [2025-11-15 22:13:16.698] [7934] [139886327420160] [llmmodels] [WARN] [operation_factory.cpp:42] OperationName: TransdataOperation not find in operation factory map [2025-11-15 22:13:22,379] [7933] [139649439929600] [llmmodels] [INFO] [model_runner.py-282] : model: FlashQwen2vlForCausalLM( (rotary_embedding): PositionRotaryEmbedding() (attn_mask): AttentionMask() (vision_tower): Qwen25VisionTransformerPretrainedModelATB( (encoder): Qwen25VLVisionEncoderATB( (layers): ModuleList( (0-31): 32 x Qwen25VLVisionLayerATB( (attn): VisionAttention( (qkv): TensorParallelColumnLinear( (linear): FastLinear() ) (proj): TensorParallelRowLinear( (linear): FastLinear() ) ) (mlp): VisionMlp( (gate_up_proj): TensorParallelColumnLinear( (linear): FastLinear() ) (down_proj): TensorParallelRowLinear( (linear): FastLinear() ) ) (norm1): BaseRMSNorm() (norm2): BaseRMSNorm() ) ) (patch_embed): FastPatchEmbed( (proj): TensorReplicatedLinear( (linear): FastLinear() ) ) (patch_merger): PatchMerger( (patch_merger_mlp_0): TensorParallelColumnLinear( (linear): FastLinear() ) (patch_merger_mlp_2): TensorParallelRowLinear( (linear): FastLinear() ) (patch_merger_ln_q): BaseRMSNorm() ) ) (rotary_pos_emb): VisionRotaryEmbedding() ) (language_model): FlashQwen2UsingMROPEForCausalLM( (rotary_embedding): PositionRotaryEmbedding() (attn_mask): AttentionMask() (transformer): FlashQwenModel( (wte): TensorEmbeddingWithoutChecking() (h): ModuleList( (0-27): 28 x FlashQwenLayer( (attn): FlashQwenAttention( (rotary_emb): PositionRotaryEmbedding() (c_attn): TensorParallelColumnLinear( (linear): FastLinear() ) (c_proj): TensorParallelRowLinear( (linear): FastLinear() ) ) (mlp): QwenMLP( (act): SiLU() (w2_w1): TensorParallelColumnLinear( (linear): FastLinear() ) (c_proj): TensorParallelRowLinear( (linear): FastLinear() ) ) (ln_1): QwenRMSNorm() (ln_2): QwenRMSNorm() ) ) (ln_f): QwenRMSNorm() ) (lm_head): TensorParallelHead( (linear): FastLinear() ) ) ) [2025-11-15 22:13:24,268] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-134] : hbm_capacity(GB): 87.5078125, init_memory(GB): 11.376015624962747 [2025-11-15 22:13:24,789] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-342] : pa_runner: PARunner(model_path=/models/Qwen2.5-VL-7B-Instruct/, input_text=请用超过500个字详细说明图片的内容,并仔细判断画面中的人物是否有吸烟动作。, max_position_embeddings=None, max_input_length=16384, max_output_length=1024, max_prefill_tokens=-1, load_tokenizer=True, enable_atb_torch=False, max_prefill_batch_size=None, max_batch_size=1, dtype=torch.float16, block_size=128, model_config=ModelConfig(num_heads=14, num_kv_heads=2, num_kv_heads_origin=4, head_size=128, k_head_size=128, v_head_size=128, num_layers=28, device=npu:0, dtype=torch.float16, soc_info=NPUSocInfo(soc_name='', soc_version=200, need_nz=True, matmul_nd_nz=False), kv_quant_type=None, fa_quant_type=None, mapping=Mapping(world_size=2, rank=0, num_nodes=1,pp_rank=0, pp_groups=[[0], [1]], micro_batch_size=1, attn_dp_groups=[[0], [1]], attn_tp_groups=[[0, 1]], attn_inner_sp_groups=[[0], [1]], attn_cp_groups=[[0], [1]], attn_o_proj_tp_groups=[[0], [1]], mlp_tp_groups=[[0, 1]], moe_ep_groups=[[0], [1]], moe_tp_groups=[[0, 1]]), cla_share_factor=1, model_type=qwen2_5_vl, enable_nz=False), max_memory=93960798208, [2025-11-15 22:13:24,794] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-122] : ---------------Begin warm_up--------------- [2025-11-15 22:13:24,794] [7933] [139649439929600] [llmmodels] [INFO] [cache.py-154] : kv cache will allocate 0.46484375GB memory [2025-11-15 22:13:24,821] [7934] [139886327420160] [llmmodels] [INFO] [cache.py-154] : kv cache will allocate 0.46484375GB memory [2025-11-15 22:13:24,827] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1139] : ------total req num: 1, infer start-------- [2025-11-15 22:13:26,002] [7934] [139886327420160] [llmmodels] [INFO] [flash_causal_qwen2.py-680] : <<<<<<<after transdata k_caches[0].shape=torch.Size([136, 16, 128, 16]) [2025-11-15 22:13:26,023] [7933] [139649439929600] [llmmodels] [INFO] [flash_causal_qwen2.py-676] : <<<<<<< ori k_caches[0].shape=torch.Size([136, 16, 128, 16]) [2025-11-15 22:13:26,023] [7933] [139649439929600] [llmmodels] [INFO] [flash_causal_qwen2.py-680] : <<<<<<<after transdata k_caches[0].shape=torch.Size([136, 16, 128, 16]) [2025-11-15 22:13:26,024] [7933] [139649439929600] [llmmodels] [INFO] [flash_causal_qwen2.py-705] : >>>>>>id of kcache is 139645634198608 id of vcache is 139645634198320 [2025-11-15 22:13:34,363] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1294] : Prefill time: 9476.590633392334ms, Prefill average time: 9476.590633392334ms, Decode token time: 54.94809150695801ms, E2E time: 9531.538724899292ms [2025-11-15 22:13:34,363] [7934] [139886327420160] [llmmodels] [INFO] [generate.py-1294] : Prefill time: 9452.020645141602ms, Prefill average time: 9452.020645141602ms, Decode token time: 54.654598236083984ms, E2E time: 9506.675243377686ms [2025-11-15 22:13:34,366] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1326] : -------------------performance dumped------------------------ [2025-11-15 22:13:34,371] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1329] : | batch_size | input_seq_len | output_seq_len | e2e_time(ms) | prefill_time(ms) | decoder_token_time(ms) | prefill_count | prefill_average_time(ms) | |-------------:|----------------:|-----------------:|---------------:|-------------------:|-------------------------:|----------------:|---------------------------:| | 1 | 16384 | 2 | 9531.54 | 9476.59 | 54.95 | 1 | 9476.59 | /usr/local/lib64/python3.11/site-packages/torchvision/transforms/functional.py:1603: UserWarning: The default value of the antialias parameter of all the resizing transforms (Resize(), RandomResizedCrop(), etc.) will change from None to True in v0.17, in order to be consistent across the PIL and Tensor backends. To suppress this warning, directly pass antialias=True (recommended, future default), antialias=None (current default, which means False for Tensors and True for PIL), or antialias=False (only works on Tensors - PIL will still use antialiasing). This also applies if you are using the inference transforms from the models weights: update the call to weights.transforms(antialias=True). warnings.warn( [2025-11-15 22:13:35,307] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-148] : warmup_memory(GB): 15.75 [2025-11-15 22:13:35,307] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-153] : ---------------End warm_up--------------- /usr/local/lib64/python3.11/site-packages/torchvision/transforms/functional.py:1603: UserWarning: The default value of the antialias parameter of all the resizing transforms (Resize(), RandomResizedCrop(), etc.) will change from None to True in v0.17, in order to be consistent across the PIL and Tensor backends. To suppress this warning, directly pass antialias=True (recommended, future default), antialias=None (current default, which means False for Tensors and True for PIL), or antialias=False (only works on Tensors - PIL will still use antialiasing). This also applies if you are using the inference transforms from the models weights: update the call to weights.transforms(antialias=True). warnings.warn( [2025-11-15 22:13:35,363] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1139] : ------total req num: 1, infer start-------- [2025-11-15 22:13:50,021] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1294] : Prefill time: 1004.0028095245361ms, Prefill average time: 1004.0028095245361ms, Decode token time: 13.301290491575836ms, E2E time: 14611.222982406616ms [2025-11-15 22:13:50,021] [7934] [139886327420160] [llmmodels] [INFO] [generate.py-1294] : Prefill time: 1067.9974555969238ms, Prefill average time: 1067.9974555969238ms, Decode token time: 13.300292536193908ms, E2E time: 14674.196720123291ms [2025-11-15 22:13:50,025] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1326] : -------------------performance dumped------------------------ [2025-11-15 22:13:50,028] [7933] [139649439929600] [llmmodels] [INFO] [generate.py-1329] : | batch_size | input_seq_len | output_seq_len | e2e_time(ms) | prefill_time(ms) | decoder_token_time(ms) | prefill_count | prefill_average_time(ms) | |-------------:|----------------:|-----------------:|---------------:|-------------------:|-------------------------:|----------------:|---------------------------:| | 1 | 1675 | 1024 | 14611.2 | 1004 | 13.3 | 1 | 1004 | [2025-11-15 22:13:50,035] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-385] : Question[0]: [{'image': '/root/pic/test.jpg'}, {'text': '请用超过500个字详细说明图片的内容,并仔细判断画面中的人物是否有吸烟动作。'}] [2025-11-15 22:13:50,035] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-386] : Answer[0]: 这张图片展示了一个无人机航拍的场景,画面中可以看到两名工人站在一个雪地或冰面上。他们穿着橙色的安全背心和红色的安全帽,显得非常醒目。背景中可以看到一些雪地和一些金属结构,可能是桥梁或工业设施的一部分。 从图片的细节来看,画面右侧的工人右手放在嘴边,似乎在吸烟。他的姿势和动作与吸烟者的典型姿势相符。然而,由于图片的分辨率和角度限制,无法完全确定这个动作是否真实发生。如果要准确判断,可能需要更多的视频片段或更清晰的图像。 从无人机航拍的角度来看,这个场景可能是在进行某种工业或建筑项目的检查或监控。两名工人可能正在进行现场检查或讨论工作事宜。雪地和金属结构表明这可能是一个寒冷的冬季,或者是一个寒冷的气候区域。 无人机航拍技术在工业和建筑领域中非常常见,因为它可以提供高空视角,帮助工程师和管理人员更好地了解现场情况。这种技术不仅可以节省时间和成本,还可以提高工作效率和安全性。在进行航拍时,确保遵守当地的法律法规和安全规定是非常重要的。 总的来说,这张图片展示了一个无人机航拍的场景,画面中两名工人站在雪地上,其中一人似乎在吸烟。虽然无法完全确定这个动作是否真实发生,但根据他们的姿势和动作,可以合理推测这个动作的存在。 [2025-11-15 22:13:50,035] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-387] : Generate[0] token num: 282 [2025-11-15 22:13:50,035] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-389] : Latency(s): 14.721353530883789 [2025-11-15 22:13:50,035] [7933] [139649439929600] [llmmodels] [INFO] [run_pa.py-390] : Throughput(tokens/s): 19.15584728050956 本文详细介绍了在OrangePi AI Studio上使用Docker容器部署MindIE环境并运行Qwen2.5-VL-7B-Instruct多模态大模型实现吸烟动作识别的完整过程,验证了在Ascned 310p设备上运行多模态理解大模型的可靠性。
-
《DeepSeek-OCR: Contexts Optical Compression》提出用“光学压缩”思路,就是说,我们不让AI‘阅读’文字,我们让它‘看’文字。不再一个一个地把“文字token”(可以理解为单词或字符)喂给AI了,而是先把整页文档“拍一张照片”,然后把这张高分辨率图片喂给AI。效果怎么样呢?论文的数据给出的答案:* 10倍压缩,97%的精度!实验显示,当“文字token”的数量是“视觉token”的10倍以内时(比如把1000个单词压缩成100个视觉单位),模型“解压”还原文字的精度高达97%。* 20倍压缩,依然可用!即便是在接近20倍的极限压缩下(比如把1200多个单词硬塞进64个视觉单位),模型的准确率竟然还能保持在60%左右。这就像你只看一眼超级模糊的缩略图,就能猜出原图的大部分内容。这个有点颠覆当前的AI处理的思路,但是有点像人类的学习的路径,因为人类学习的方式,获取信息的方式,绝大部分是通过视觉,也就是通过眼睛看来获取的。所以这篇论文提出的思路,你怎么看呢?觉得它有发展前途,还是可能不太看好?
-
松材线虫病边缘模型训练与推理部署本文详细介绍了松材线虫病检测的边缘模型训练与推理部署全流程。首先,针对无人机拍摄的4032×3024原始图像进行预处理,缩放到1024×1024避免内存溢出,并定义了9个类别(包括麻栎、罩网、疑似、早期、轻度、中度、重度、死亡和逾年)。随后采用20%重叠率对图像进行切分,生成训练集60000张、验证集6495张的sahi数据集。模型训练基于yolo11s.yaml配置,在pwd数据集上进行10个Epoch的训练,虽然实际应用建议至少100个Epoch。评估结果显示,模型在pwd(重度)类别上表现最佳(mAP50达0.707),而pwd_early(早期)类别表现较差。为提升推理效率,将模型导出为TensorRT FP16引擎,GPU推理速度提升高达5倍,单张图片推理耗时约20ms。最后,通过Gradio构建了用户友好的检测应用,实现了松材线虫病的实时检测功能,为林业病害监测提供了有效的技术解决方案,具有较强的实用价值和推广前景。1. 原始数据无人机拍摄原始图像大小是4032 x 3024,这里缩放到1024 x 1024,避免在模型训练时内存溢出:%%writefile pwd.yaml # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..] path: /home/jetson/ultralytics/dataset/pwd # dataset root dir (absolute path) train: train/images # train images (relative to 'path') val: val/images # val images (relative to 'path') test: # test images (optional) # Classes,类别 names: 0: hardwood # 麻栎 1: net # 罩网 2: abnormal # 疑似 3: pwd_pre_early # 早期 4: pwd_early # 轻度 5: pwd_moderate # 中度 6: pwd # 重度 7: dead_recent # 死亡 8: dead # 逾年 Overwriting pwd.yaml训练集3000张图像,验证集529张图像,查看验证集标注情况:import os import cv2 import yaml import random import numpy as np from matplotlib import pyplot as plt %matplotlib inline with open('pwd.yaml', 'r', encoding='utf-8') as f: data = yaml.load(f.read(), Loader=yaml.FullLoader) classes = data['names'] file_path = os.path.join(data['path'], 'val/images') file_list = os.listdir(file_path) img_paths = random.sample(file_list, 4) img_lists = [] for img_path in img_paths: img_path = os.path.join(file_path, img_path) img = cv2.imread(img_path) h, w, _ = img.shape tl = round(0.002 * (h + w) / 2) + 1 color = (0, 255, 255) if img_path.endswith('.png'): with open(img_path.replace("images", "labels").replace(".png", ".txt")) as f: labels = f.readlines() if img_path.endswith('.jpg'): with open(img_path.replace("images", "labels").replace(".jpg", ".txt")) as f: labels = f.readlines() if img_path.endswith('.jpeg'): with open(img_path.replace("images", "labels").replace(".jpeg", ".txt")) as f: labels = f.readlines() for label in labels: l, x, y, wc, hc = [float(x) for x in label.strip().split()] x1 = int((x - wc / 2) * w) y1 = int((y - hc / 2) * h) x2 = int((x + wc / 2) * w) y2 = int((y + hc / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), color, thickness=tl, lineType=cv2.LINE_AA) cv2.putText(img,classes[int(l)],(x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2, cv2.LINE_AA) img_lists.append(cv2.resize(img, (1024, 1024))) image = np.concatenate([np.concatenate(img_lists[:2], axis=1), np.concatenate(img_lists[2:], axis=1)], axis=0) cv2.imwrite("sample-pwd.png", image) plt.rcParams["figure.figsize"] = (16, 16) plt.imshow(image[:,:,::-1]) plt.axis('off') plt.show() 2. 切分数据对dataset/pwd数据集进行图像切分,切分大小为1024 x 1024,重叠率是20%,生成新的数据集dataset/pwd-sahi:%%writefile pwd-sahi.yaml # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..] path: /home/jetson/ultralytics/dataset/pwd-sahi # dataset root dir (absolute path) train: train/images # train images (relative to 'path') val: val/images # val images (relative to 'path') test: # test images (optional) # Classes,类别 names: 0: hardwood # 麻栎 1: net # 罩网 2: abnormal # 疑似 3: pwd_pre_early # 早期 4: pwd_early # 轻度 5: pwd_moderate # 中度 6: pwd # 重度 7: dead_recent # 死亡 8: dead # 逾年 Overwriting pwd-sahi.yaml其中训练集60000张图像(部分为背景图),验证集6495张图像(不含背景图),查看验证集的标注情况:import os import cv2 import yaml import random import numpy as np from matplotlib import pyplot as plt %matplotlib inline with open('pwd-sahi.yaml', 'r', encoding='utf-8') as f: data = yaml.load(f.read(), Loader=yaml.FullLoader) classes = data['names'] file_path = os.path.join(data['path'], 'val/images') file_list = os.listdir(file_path) img_paths = random.sample(file_list, 4) img_lists = [] for img_path in img_paths: img_path = os.path.join(file_path, img_path) img = cv2.imread(img_path) h, w, _ = img.shape tl = round(0.002 * (h + w) / 2) + 1 color = (0, 255, 255) if img_path.endswith('.png'): with open(img_path.replace("images", "labels").replace(".png", ".txt")) as f: labels = f.readlines() if img_path.endswith('.jpg'): with open(img_path.replace("images", "labels").replace(".jpg", ".txt")) as f: labels = f.readlines() if img_path.endswith('.jpeg'): with open(img_path.replace("images", "labels").replace(".jpeg", ".txt")) as f: labels = f.readlines() for label in labels: l, x, y, wc, hc = [float(x) for x in label.strip().split()] x1 = int((x - wc / 2) * w) y1 = int((y - hc / 2) * h) x2 = int((x + wc / 2) * w) y2 = int((y + hc / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), color, thickness=tl, lineType=cv2.LINE_AA) cv2.putText(img,classes[int(l)],(x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2, cv2.LINE_AA) img_lists.append(cv2.resize(img, (1024, 1024))) image = np.concatenate([np.concatenate(img_lists[:2], axis=1), np.concatenate(img_lists[2:], axis=1)], axis=0) cv2.imwrite("sample-pwd-sahi.png", image) plt.rcParams["figure.figsize"] = (16, 16) plt.imshow(image[:,:,::-1]) plt.axis('off') plt.show() 3. 模型训练我们加载yolo11s.yaml模型的配置文件在dataset/pwd数据集上训练10个Epoch,模型的训练结果保存在pine_wilt_disease/yolo11s_10目录下:%%writefile train.py from ultralytics import YOLO # Load a model model = YOLO('yolo11s.yaml') # load yaml model # Train the model results = model.train(data='pwd.yaml', epochs=10, imgsz=640, workers=4, batch=8, project="pine_wilt_disease", name="yolo11s_10") Overwriting train.py在终端中运行:/home/jetson/ultralytics/train.sh在另一个终端中运行/home/jetson/ultralytics/tensorboard.sh可以监控模型的训练情况:4. 模型评估加载训练好的模型,这里我们仅训练了10个Epoch,实际训练至少100个Epoch才能取得较好的效果:from ultralytics import YOLO # Load a model model = YOLO('pine_wilt_disease/yolo11s_10/weights/best.pt') # load the best model # Evaluate the model metrics = model.val( data='pwd.yaml', # 数据集配置 imgsz=640, # 模型输入大小 workers=4, # 数据加载线程 batch=8, # 验证批次大小 plots=True, # 生成验证结果图 split='val' # 指定使用验证集 ) Ultralytics 8.3.55 🚀 Python-3.10.12 torch-2.5.0a0+872d972e41.nv24.08 CUDA:0 (Orin, 7620MiB) YOLO11s summary (fused): 238 layers, 9,416,283 parameters, 0 gradients, 21.3 GFLOPs val: Scanning /home/jetson/ultralytics/dataset/pwd/val/labels.cache... 529 images, 0 backgrounds, 0 corrupt: 100%|██████████| 529/529 [00:00<?, ?it/s] Class Images Instances Box(P R mAP50 mAP50-95): 100%|██████████| 67/67 [00:22<00:00, 2.92it/s] all 529 8612 0.602 0.445 0.442 0.261 net 383 4210 0.681 0.625 0.683 0.401 pwd_early 167 375 1 0 0.0362 0.0168 pwd_moderate 253 503 0.4 0.225 0.224 0.108 pwd 383 1141 0.582 0.765 0.707 0.462 dead_recent 376 1456 0.503 0.443 0.444 0.26 dead 229 927 0.444 0.613 0.557 0.318 Speed: 0.9ms preprocess, 24.5ms inference, 0.0ms loss, 4.1ms postprocess per image Results saved to runs/detect/val注意,图片实际标注的类别只有6类,不包含麻栎和疑似。5. 模型导出导出到TensorRT,GPU推理速度提升高达5倍:https://docs.ultralytics.com/zh/integrations/tensorrt/from ultralytics import YOLO model = YOLO("pine_wilt_disease/yolo11s_10/weights/best.pt") # TensorRT FP16 model.export(format="engine", imgsz=640, batch=1, half=True) WARNING ⚠️ TensorRT requires GPU export, automatically assigning device=0 Ultralytics 8.3.55 🚀 Python-3.10.12 torch-2.5.0a0+872d972e41.nv24.08 CUDA:0 (Orin, 7620MiB) YOLO11s summary (fused): 238 layers, 9,416,283 parameters, 0 gradients, 21.3 GFLOPs [34m[1mPyTorch:[0m starting from 'pine_wilt_disease/yolo11s_10/weights/best.pt' with input shape (1, 3, 640, 640) BCHW and output shape(s) (1, 13, 8400) (18.3 MB) [34m[1mONNX:[0m starting export with onnx 1.17.0 opset 19... [34m[1mONNX:[0m slimming with onnxslim 0.1.47... [34m[1mONNX:[0m export success ✅ 3.2s, saved as 'pine_wilt_disease/yolo11s_10/weights/best.onnx' (36.2 MB) [34m[1mTensorRT:[0m starting export with TensorRT 10.7.0... [11/15/2025-16:23:19] [TRT] [I] [MemUsageChange] Init CUDA: CPU -2, GPU +0, now: CPU 1395, GPU 7158 (MiB) [11/15/2025-16:23:25] [TRT] [I] [MemUsageChange] Init builder kernel library: CPU +970, GPU +258, now: CPU 2322, GPU 7418 (MiB) [11/15/2025-16:23:26] [TRT] [I] ---------------------------------------------------------------- [11/15/2025-16:23:26] [TRT] [I] Input filename: pine_wilt_disease/yolo11s_10/weights/best.onnx [11/15/2025-16:23:26] [TRT] [I] ONNX IR version: 0.0.9 [11/15/2025-16:23:26] [TRT] [I] Opset version: 19 [11/15/2025-16:23:26] [TRT] [I] Producer name: pytorch [11/15/2025-16:23:26] [TRT] [I] Producer version: 2.5.0 [11/15/2025-16:23:26] [TRT] [I] Domain: [11/15/2025-16:23:26] [TRT] [I] Model version: 0 [11/15/2025-16:23:26] [TRT] [I] Doc string: [11/15/2025-16:23:26] [TRT] [I] ---------------------------------------------------------------- [34m[1mTensorRT:[0m input "images" with shape(1, 3, 640, 640) DataType.FLOAT [34m[1mTensorRT:[0m output "output0" with shape(1, 13, 8400) DataType.FLOAT [34m[1mTensorRT:[0m building FP16 engine as pine_wilt_disease/yolo11s_10/weights/best.engine [11/15/2025-16:23:26] [TRT] [I] Local timing cache in use. Profiling results in this builder pass will not be stored. [11/15/2025-16:28:08] [TRT] [I] Compiler backend is used during engine build. [11/15/2025-16:31:48] [TRT] [I] Detected 1 inputs and 1 output network tensors. [11/15/2025-16:31:53] [TRT] [I] Total Host Persistent Memory: 543184 bytes [11/15/2025-16:31:53] [TRT] [I] Total Device Persistent Memory: 0 bytes [11/15/2025-16:31:53] [TRT] [I] Max Scratch Memory: 2764800 bytes [11/15/2025-16:31:53] [TRT] [I] [BlockAssignment] Started assigning block shifts. This will take 162 steps to complete. [11/15/2025-16:31:53] [TRT] [I] [BlockAssignment] Algorithm ShiftNTopDown took 19.653ms to assign 10 blocks to 162 nodes requiring 19046912 bytes. [11/15/2025-16:31:53] [TRT] [I] Total Activation Memory: 19046400 bytes [11/15/2025-16:31:53] [TRT] [I] Total Weights Memory: 18914082 bytes [11/15/2025-16:31:53] [TRT] [I] Compiler backend is used during engine execution. [11/15/2025-16:31:53] [TRT] [I] Engine generation completed in 506.948 seconds. [11/15/2025-16:31:53] [TRT] [I] [MemUsageStats] Peak memory usage of TRT CPU/GPU memory allocators: CPU 2 MiB, GPU 140 MiB [34m[1mTensorRT:[0m export success ✅ 519.0s, saved as 'pine_wilt_disease/yolo11s_10/weights/best.engine' (21.6 MB) Export complete (519.7s) Results saved to [1m/home/jetson/ultralytics/pine_wilt_disease/yolo11s_10/weights[0m Predict: yolo predict task=detect model=pine_wilt_disease/yolo11s_10/weights/best.engine imgsz=640 half Validate: yolo val task=detect model=pine_wilt_disease/yolo11s_10/weights/best.engine imgsz=640 data=pwd.yaml half Visualize: https://netron.app导出FP16精度的量化模型大概需要10分钟左右。6. 模型推理使用TensorRT引擎加载模型对验证集的部分图片进行推理,每张图片的推理耗时约20ms:import cv2 import glob from ultralytics import YOLO import matplotlib.pyplot as plt %matplotlib inline # Load the TensorRT engine model model = YOLO("pine_wilt_disease/yolo11s_10/weights/best.engine") # Define the prediction function def predict(image_path): reuslts = model.predict(image_path, conf=0.45, iou=0.55) return reuslts[0].plot() # Load the images for inference images_path = glob.glob("dataset/pwd/val/images/*.jpeg") # Perform inference and display results for image_path in images_path[:10]: result = predict(image_path) result = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) result = cv2.resize(result, (4032 // 4, 3024 // 4)) plt.imshow(result) plt.axis("off") plt.show() WARNING ⚠️ Unable to automatically guess model task, assuming 'task=detect'. Explicitly define task for your model, i.e. 'task=detect', 'segment', 'classify','pose' or 'obb'. Loading pine_wilt_disease/yolo11s_10/weights/best.engine for TensorRT inference... [11/15/2025-16:31:54] [TRT] [I] Loaded engine size: 21 MiB [11/15/2025-16:31:54] [TRT] [I] [MemUsageChange] TensorRT-managed allocation in IExecutionContext creation: CPU +0, GPU +18, now: CPU 0, GPU 36 (MiB) image 1/1 /home/jetson/ultralytics/dataset/pwd/val/images/1d1d160a-ae4f-4fe4-801d-f001d4e7ff6d.jpeg: 640x640 4 nets, 1 pwd, 1 dead_recent, 20.1ms Speed: 45.6ms preprocess, 20.1ms inference, 49.3ms postprocess per image at shape (1, 3, 640, 640) ... 构建Gradio应用程序,上传图片实现松材线虫病检测的功能:至此,本章结束。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签