【RustyML入门】2.7. KMeans聚类
2.7. KMeans聚类KMeans把样本划分到固定数量的簇里。它交替执行两步先把每个点分配给最近的质心再把每个质心重新计算为其成员的均值。RustyML 的实现是一套并行的 Lloyd 算法配上 k-means 初始化和「重启若干次、取最优」的策略。如果你熟悉 scikit-learn 的sklearn.cluster.KMeans那套心智模型的大部分都能直接搬过来用。唯一一处刻意不同的默认值是n_init原因见 2.7.1。2.7.1. 估计器的工作原理一次fit调用会把整套流程跑n_init遍保留 inertia 最低的那一遍。每一遍里质心都从k-means初始化开始。第一个中心是从样本中均匀随机抽取的一个点。之后每个中心都从剩余的点里抽取抽中的概率正比于该点到最近的已选中心的平方距离经典的 D^2 轮盘赌。这样能把初始中心尽量拉开给 Lloyd 迭代一个比均匀随机初始化更好的起点。如果所有候选点的平方距离都为零实现会转而对这个中心做均匀随机挑选。这种情况只有在所有点都与已选中心重复时才会发生。初始化之后每轮迭代做两件事分配步把每个点归到最近的质心更新步把每个质心替换成分配给它的那些点的均值。当质心不再移动时迭代停止。收敛判据比较的是所有质心的平方位移之和与一个按方差缩放的容差。这个阈值等于数据每维总体方差的均值再乘以tol。所以tol是相对容差而不是绝对距离。这与 scikit-learn 的约定一致。收敛解是一个不动点每个质心都恰好等于分配给它的点的均值。一次因为用光预算、而不是因为收敛而结束的拟合在返回之前会多跑一趟分配。Lloyd 循环先按当前质心给点打标签然后才装入更新后的质心。所以停在max_iterations上会让labels和inertia描述的是旧质心而get_centroids报告的却是新质心。这样一来predict(x)就会与get_labels()对不上。最后这一趟按模型真正存下来的质心重新分配。scikit-learn 出于同样的原因重跑它最后那一步 E-step。与 scikit-learn 唯一一处刻意的差别是重启次数。这里n_init默认是 10。scikit-learn 在 k-means 下的n_initauto是 1。这不是疏漏。scikit-learn 的默认值建立在它的贪心k-means 之上每个中心会抽2 ln(k)个候选并留下最好的那个。所以那里单次初始化本身方差就已经很低。RustyML 用的是朴素 k-means每个中心只做一次 D^2 抽取。重启机制存在的意义正是为了弥补这种更高方差的初始化。想要严格对齐 scikit-learn就传with_n_init(1)。这样做之后预期拟合结果会随之改变。各次重启的种子由random_state确定性地派生所以带种子的拟合仍然可复现。2.7.2. 构造模型构造函数接收 3 个位置参数并会即时校验。配置不合法会在构造时就失败而不是拖到fit。pub fn new(n_clusters: usize, max_iterations: usize, tolerance: f64) - ResultSelf, Error参数位置类型含义n_clusters第 1 个usize要形成的簇数k。必须大于 0。max_iterations第 2 个usize每次重启内部 Lloyd 迭代的上限。必须大于 0。tolerance第 3 个f64相对收敛容差按特征方差缩放。必须为正且有限。任何一条不满足都会返回Error::InvalidParametern_clusters 0、max_iterations 0或者tolerance为零、为负、NaN或无穷。注意它和数据校验错误之间的不对称。越界的超参数会返回InvalidParameter。数据里的非有限值则返回NonFinite。这个区分是全 crate 通用的约定。KMeans::default()给你n_clusters 8、max_iterations 300、tolerance 1e-4、n_init 10且不带种子。这份配置永远合法。余下两项设置是 builder 步骤它们各自拿走实例的所有权、再把它交还所以可以接在new后面链式调用。with_random_state(seed)不会失败。with_n_init(n)返回Result因为0次重启会触发Error::InvalidParameterlet mut km KMeans::new(3, 300, 1e-4) .unwrap() .with_n_init(1) // 对齐 scikit-learn返回 Result .unwrap() .with_random_state(42); // 返回 Self不带种子时k-means 从系统熵取随机数每次fit都会得到不同的划分。带上种子fit就可复现详见 2.7.6。这种可复现性也覆盖每一次重启每次重启都会从你设的种子确定性地派生出自己的子种子。2.7.3. 训练、预测与读取结果驱动模型的方法有 3 个它们在返回值和改动的状态上各不相同。fit(mut self, data)原地训练模型返回Resultmut Self, Error。它会算出并存下质心、训练集标签、inertia 和迭代次数。这 4 个值都描述胜出的那次重启。predict(self, data)把新矩阵的每一行归到最近的已拟合质心返回一个持有所有权的Array1isize。它以不可变方式借用self不改动任何已存状态所以拟合一次之后想调用多少次都行。标签用的是有符号类型而非无符号类型。这样才能让 crate 里每个聚类估计器共享同一种标签类型。DBSCAN 和 MeanShift 都用-1表示噪声共享的标签类型让它们不加转换就能喂给 5.3. 聚类指标 里的各项指标。k-means 自己永远不会返回负标签。fit_predict(mut self, data)会调用fit然后返回训练标签的一份克隆。只想要刚训练那批数据的标签时用它。想给新样本打分时改用fit加predict。已拟合的状态通过一组 getter 暴露出来fit之前它们都返回NoneGetter返回说明get_centroids()OptionArray2f64形状(n_clusters, n_features)。对应 scikit-learn 的cluster_centers_。get_labels()OptionArray1isize训练集的归属。对应 scikit-learn 的labels_。get_inertia()Optionf64各点到最近质心的平方距离之和。对应 scikit-learn 的inertia_。无论是否收敛都与get_centroids()保持一致。get_actual_iterations()Optionusize胜出那次重启实际跑的迭代次数1..max_iterations。对应 scikit-learn 的n_iter_。get_n_clusters()/get_max_iterations()/get_tolerance()/get_n_init()/get_random_state()普通值 /Optionu64回读配置本身。fit会报 3 类数据错误。矩阵行数为零时返回Error::EmptyInput。任何值为NaN或无穷时返回Error::NonFinite。样本数少于簇数时返回Error::InvalidInput因为点数不到k个就摆不下k个质心。predict还会另外报 2 种错误。在fit之前调用返回Error::NotFitted。特征数与训练数据对不上返回Error::DimensionMismatch。它还会做和fit一样的空输入与非有限值检查。2.7.4. 端到端聚类三个数据簇3 个紧凑、彼此分得很开的数据簇是最经典的正确性自检。任何正确的 k3 拟合都必须把每个数据簇单独分成一类。这个例子用了一份小而确定的数据集数据本身不含随机数再加一个固定种子。它瞬间就能跑完结果的结构也在意料之中。userustyml::machine_learning::KMeans;usendarray::{array,Array2};fnmain(){// 三个数据簇各 5 个点中心在 (0,0)、(10,0)、(5,10)。letdata:Array2f64array![[-0.05,0.03],[0.04,-0.02],[0.01,0.05],[-0.03,-0.04],[0.02,0.01],[9.95,0.03],[10.04,-0.02],[10.01,0.05],[9.97,-0.04],[10.02,0.01],[4.95,10.03],[5.04,9.98],[5.01,10.05],[4.97,9.96],[5.02,10.01],];letmutkmKMeans::new(3,300,1e-4).unwrap().with_random_state(42);km.fit(data).unwrap();letlabelskm.get_labels().unwrap();letcentroidskm.get_centroids().unwrap();println!(labels: {:?},labels);println!(centroids: {:?},centroids);println!(inertia: {:.6},km.get_inertia().unwrap());println!(iters: {},km.get_actual_iterations().unwrap());// 给落在各数据簇真实中心上的新样本打分。letnew_pointsarray![[0.0,0.0],[10.0,0.0],[5.0,10.0]];letpredictedkm.predict(new_points).unwrap();println!(new-point labels: {:?},predicted);}具体的簇编号是任意的k-means 按发现顺序给簇编号所以哪个数据簇成为 0 号取决于种子。但结构是固定的labels: 每个数据簇的 5 个点共享同一个编号。3 个数据簇会拿到 3 个互不相同的编号 0、1、2 的某种排列。 centroids: 形状 (3, 2)。三行按某种顺序分别落在 (0,0)、(10,0)、(5,10) 附近约 0.1 的范围内。 inertia: 一个很小的正 f64各点到质心距离的平方和。 iters: 若干次远低于 max_iterations。 new-point labels: 每个测试点都映射到它所在数据簇对应的那个编号。簇编号取决于排列方式所以永远不要用相等去比较 2 个分别拟合的模型的标签。应该改用排列不变的指标比如 5.3. 聚类指标 里的调整兰德指数。2.7.5. 如何选择 kk-means 没法告诉你k是多少得你自己给出。有 2 种方法能帮你缩小范围RustyML 为两者都备好了原料。肘部法把 inertia 对k画成曲线。inertia 会随着k增大而单调下降因为质心越多平方距离之和只会更小。到k n时它会降到零。要找的是「肘部」也就是下降变平的那个点。inertia 可以直接从get_inertia读出来。轮廓系数更有决断力因为它有一个内部最优值而不是单调趋势。对每个点它衡量的是这个点离自己所在的簇比离最近的其他簇近多少。它把这些值平均成[-1, 1]里的一个分数越高越好。metrics 模块把它作为silhouette_score提供。它接收特征矩阵、标签和一个DistanceCalculationMetric。它只对2..n-1个不同的簇有定义所以没法给k 1打分。userustyml::machine_learning::KMeans;userustyml::metrics::silhouette_score;userustyml::math::DistanceCalculationMetric;usendarray::{array,Array2};fnmain(){letdata:Array2f64array![[-0.05,0.03],[0.04,-0.02],[0.01,0.05],[-0.03,-0.04],[0.02,0.01],[9.95,0.03],[10.04,-0.02],[10.01,0.05],[9.97,-0.04],[10.02,0.01],[4.95,10.03],[5.04,9.98],[5.01,10.05],[4.97,9.96],[5.02,10.01],];println!( k inertia silhouette);forkin1..5usize{letmutkmKMeans::new(k,300,1e-4).unwrap().with_random_state(42);letlabelskm.fit_predict(data).unwrap();letinertiakm.get_inertia().unwrap();ifk2{letssilhouette_score(data,labels,DistanceCalculationMetric::Euclidean);println!({k:2} {inertia:8.4} {s:7.4});}else{println!({k:2} {inertia:8.4} (n/a));}}}在这 3 个干净的数据簇上inertia 从k 1到k 3骤降然后趋平。轮廓系数在k 3达到峰值。两者都指向真实结构。真实数据要浑浊得多所以轮廓系数的内部极大值往往能给出更清晰的信号。完整的指标清单见 5.3. 聚类指标其中还有 Davies-Bouldin 和 Calinski-Harabasz能给出独立的第二意见。2.7.6. 可复现的聚类局部种子与全局种子k-means 带随机性所以不设种子的模型每次fit都会产出不同的划分。有 2 种办法能把它钉死而且它们组合起来的行为是可预料的。局部种子用with_random_state(seed)设定。它是自足的直接为该估计器的初始化 RNG 播种。它无视任何全局状态也绝不影响其他组件。n_init次重启各自的子种子是通过一个固定的混合步骤从它派生出来的而不是靠推进同一个共享 RNG。所以某次重启的初始化不会取决于之前几次重启消耗了多少随机数。用同一个局部种子构建、并在同一份数据上拟合的 2 个模型会产出完全一致的质心、标签和 inertia。迭代次数也一样一致精确到最后一位。全局种子通过rustyml::random::set_global_seed(seed)设定能只用一次调用就固定此后在同一线程上构建并拟合的每一个未设种子的随机化组件。这包括 k-means、神经网络的初始化器、train_test_split等等。这照搬了 Keras 的全局种子行为。未设种子的 k-means 模型会在fit时从全局流里取一个独立的子种子。要复现某次运行就在重新拟合之前再设一遍全局种子。这里有 2 点需要留意。全局种子是线程局部的所以要在拟合模型的那个线程上设它。未设种子的组件还会按拟合顺序消费这个流所以它们的可复现性对顺序敏感。with_random_state种子能绕开这两个问题这正是它适合用来钉死单个估计器的原因。userustyml::machine_learning::KMeans;userustyml::random::{set_global_seed,clear_global_seed};usendarray::{array,Array2};fnmain(){letdata:Array2f64array![[0.0,0.0],[0.1,0.0],[0.0,0.1],[10.0,0.0],[10.1,0.0],[10.0,0.1],[5.0,10.0],[5.1,10.0],[5.0,10.1],];// 局部种子结果完全一致与任何全局状态无关。letmutaKMeans::new(3,300,1e-4).unwrap().with_random_state(42);letmutbKMeans::new(3,300,1e-4).unwrap().with_random_state(42);a.fit(data).unwrap();b.fit(data).unwrap();assert_eq!(a.get_labels().unwrap(),b.get_labels().unwrap());// 全局种子每次拟合前重设一遍就能复现未设种子的运行。set_global_seed(7);letmutcKMeans::new(3,300,1e-4).unwrap();c.fit(data).unwrap();letlabels_cc.get_labels().unwrap().clone();set_global_seed(7);letmutdKMeans::new(3,300,1e-4).unwrap();d.fit(data).unwrap();assert_eq!(labels_c,d.get_labels().unwrap());clear_global_seed();}这种确定性之所以成立是因为并行算术从设计上就追求可复现而不只是追求速度。具体做法见 2.7.8。整个 crate 的完整播种模型见 7.1. 可复现性与随机种子。2.7.7. 失败模式与常见陷阱**空簇。**当 Lloyd 的分配让某个质心一个点都没分到时RustyML 不会丢掉这个簇。它也不会留下一个陈旧的质心。每一轮迭代都会给每个空簇重新播种用的是离它自己所属质心最远的那个点也就是对 inertia 贡献最大的那个点。这样模型始终保持恰好n_clusters个质心并在下一轮把它从退化状态里推出来。所以get_centroids永远会返回n_clusters行。在病态数据上比如大量重复、或者k接近n标签仍可能解析出少于k个不同的值。**对特征尺度敏感。**k-means 最小化的是欧几里得距离。所以一个以千计的特征会压过一个以零点几计的特征聚类实际上就把小尺度那个特征忽略了。它没有内置的标准化。只要你的特征处在不同量级就先用 4.2. 标准化与归一化 里的工具做标准化。k-means 结果看起来不对最常见的原因就是这一个。**对离群点敏感。**质心只是普通均值所以几个极端点就能把它从簇的稠密区域拽走并抬高 inertia。数据里有离群点时要么把它们裁掉要么改用把它们当作噪声处理的基于密度的方法。2.8. DBSCAN 会显式地标出离群点。2.9. MeanShift 无需预设k就能找到密度峰值。**非球状簇。**k-means 把空间划分成质心周围的 Voronoi 元胞。所以它只能还原大致凸形、大小相近的簇。同心圆环或狭长的流形无论k取多少都能难倒它。这种几何结构正是 DBSCAN 和 2.12. t-SNE 里的流形方法要对付的。**样本太少。**要求的簇数比点数还多会返回Error::InvalidInput。它不会悄悄截断k。如果k取决于数据就在拟合前先检查n_clusters data.nrows()。2.7.8. 并行与性能分配步是开销的大头。每轮迭代它都要拿每个点去比对每个质心并行也就落在这里。每轮迭代把所有点到质心的投影当成一次并行矩阵乘积算出来见 6.2. 矩阵乘法。再用一次简短的 arg-min 扫描找出每个点最近的质心。质心更新会把每个点的那一行累加进它所属簇的累积和里做法是一次确定性分块归约见 6.3. 并行归约。k-means 初始化的距离计算也用同样的方式并行。“确定性”这个词在这里很关键。上面每个阶段都只在超过一个标定过的工作量阈值时才并行。归约始终按固定的分块顺序求和而不是按线程到达的顺序。正因如此并行路径才会给出和串行路径一样的答案。也正因如此带种子的拟合在同一台机器上才可复现不管 rayon 用了多少线程。浮点加法不满足结合律。按线程恰好完成的顺序求和会把线程数泄漏进结果里。跨不同机器或不同构建目标时算术后端最后一位上的微小差异仍有可能出现。但在同一台机器内固定种子就给出固定答案。输入较小时一切都保持单线程这样能避免在用不着的数据上白付 rayon 的协调开销。这里有 3 个阈值控制着切换点。arg-min 扫描那一步用的是 f64 扫描门限。累加那一步用的是 f64 求和门限。把每个质心除以其簇大小那一步用的是 f64 cheap-map 门限。扫描门限和求和门限都在rustyml::tuning::reduction里。cheap-map 门限在rustyml::tuning::elementwise里。如果你在聚类一些不寻常的形状、想挪动某个阈值就调它们。多数用户从不碰它们。7.3. 性能调优与并行 讲解了这些旋钮。开启show_progressfeature 构建时fit过程中会画一条实时的 inertia 与迭代进度条。这在大数据集上很趁手feature 关掉时它不产生任何开销。2.7.9. 保存与加载已训练的模型KMeans派生了 serde 的Serialize和Deserialize。配套生成的save_to_path和load_from_path方法会把整个模型持久化成一段紧凑的 postcard 二进制块其中包括质心、标签、超参数和元数据。文件扩展名并不重要因为格式始终是二进制 postcard。加载回来的模型与原模型预测完全一致连质心的最后一位都不差。引入重启机制时序列化布局多了n_init这个字段。所以旧版本写出的二进制块加载不了。请重新拟合模型、再重新保存。userustyml::machine_learning::KMeans;usendarray::{array,Array2};usestd::fs::remove_file;fnmain(){letdata:Array2f64array![[0.0,0.0],[0.1,0.0],[0.0,0.1],[10.0,0.0],[10.1,0.0],[10.0,0.1],[5.0,10.0],[5.1,10.0],[5.0,10.1],];letmutkmKMeans::new(3,300,1e-4).unwrap().with_random_state(42);km.fit(data).unwrap();km.save_to_path(kmeans_model.bin).unwrap();letloadedKMeans::load_from_path(kmeans_model.bin).unwrap();letoriginalkm.predict(data).unwrap();letrestoredloaded.predict(data).unwrap();assert_eq!(original,restored);remove_file(kmeans_model.bin).unwrap();}I/O 和反序列化的问题会以Error::Io的形式出现。加载时文件不存在是最常见的情形。持久化格式、版本兼容方面的考量以及它如何与 crate 其余部分配合见 7.2. 深入模型持久化。

相关新闻

【RustyML入门】2.6. 线性判别分析

【RustyML入门】2.6. 线性判别分析

2.6. 线性判别分析 线性判别分析(LDA)一次 fit 做两件事。第一,它是一个生成式分类器:把每个类别建模成一个高斯分布,各类均值不同、协方差矩阵在所有类别间共享,再用贝叶斯规则挑出最可能的标签。第二&am…

2026/10/17 1:27:44 阅读更多 →
2026年优质外呼机器人服务商怎么选 行业核心评判标准全梳理

2026年优质外呼机器人服务商怎么选 行业核心评判标准全梳理

近几年外呼机器人已成企业降本拓客的标配,但市面服务商鱼龙混杂,不少企业踩过封号、识别不准、意向客户漏判、售后无人管的坑,不仅没提效反而白白浪费预算。本文整理了行业6家主流外呼机器人服务商的横向测评,结合核心评判标准帮大…

2026/10/16 19:55:06 阅读更多 →
5分钟免费安装SD-PPP:Photoshop AI插件终极指南

5分钟免费安装SD-PPP:Photoshop AI插件终极指南

5分钟免费安装SD-PPP:Photoshop AI插件终极指南 【免费下载链接】sd-ppp A Photoshop AI plugin 项目地址: https://gitcode.com/gh_mirrors/sd/sd-ppp 还在为Photoshop缺少AI绘图功能而烦恼吗?SD-PPP这款免费开源的Photoshop AI插件将彻底改变你…

2026/10/17 3:42:16 阅读更多 →

最新新闻

24GB显存跑32B开源大模型:量化+动态卸载的春节实验

24GB显存跑32B开源大模型:量化+动态卸载的春节实验

春节我给自己找了一件挺拧巴的事:非要把一个32B参数的开源大模型,塞进家用那台只有24GB显存的消费级显卡里。拧巴的不是技术难度,而是时机——走亲访友最忙的那几天,客厅里主机风扇一响,整个年味就碎了一地。所以这场实…

2026/10/18 19:44:30 阅读更多 →
心电算法实战:Python滤波、R波识别与心率计算全链路解析

心电算法实战:Python滤波、R波识别与心率计算全链路解析

简介:这是一份以Python编写的心电信号处理算法合集,围绕滤波、R波识别、心率计算、特征提取、心律失常分类,以及房颤、室颤室速等异常心律识别构建,同时覆盖伪差干扰研究、可视化展示与测试工程,适合生物医学工程专业学…

2026/10/18 19:44:30 阅读更多 →
假期AI圈动态全解析:模型迭代、工具链与工程落地

假期AI圈动态全解析:模型迭代、工具链与工程落地

七天假期结束,把手机里这段时间攒下的AI圈消息重新捋了一遍,说实话比上班还累。人在景区排队,群里在刷权重更新;晚上躺床上刷手机,新框架的讨论又顶上热搜。这七天给我的感觉就是:AI圈真的没一天消停&#…

2026/10/18 19:44:30 阅读更多 →
Fetch MCP服务:让大模型拥有实时网页抓取能力

Fetch MCP服务:让大模型拥有实时网页抓取能力

最近帮一位朋友调试他的AI助手项目,聊到一个很现实的问题:模型明明很强,却答不上来昨天刚发布的技术文档。原因很简单,模型的知识有截止日期,而它自己又不会主动去翻网页。要解决这个问题,就得给模型接上一…

2026/10/18 19:44:30 阅读更多 →
vdw-Prks水合物模型:甲烷水合物相平衡高精度计算原理与实现

vdw-Prks水合物模型:甲烷水合物相平衡高精度计算原理与实现

简介:本资源是一份面向计算化学、能源材料与相平衡研究方向的科研人员及高年级本科生的MATLAB建模仿真工具,聚焦甲烷水合物在低温高压条件下的相平衡预测问题。它基于经典的van der Waals–Platteeuw(vdw-P)理论框架,并…

2026/10/18 19:44:30 阅读更多 →
GitHub 开源趋势日报 | 2026年10月8日:AI Agent 与 TypeScript 项目实战配置指南

GitHub 开源趋势日报 | 2026年10月8日:AI Agent 与 TypeScript 项目实战配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 19:43:30 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →