news 2026/10/17 6:57:21

kmodes分类数据聚类:解决用户标签/商品类目等离散变量聚类难题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kmodes分类数据聚类:解决用户标签/商品类目等离散变量聚类难题

简介:本资源是面向数据科学学习者与Python开发者的kmodes聚类算法开源实现,专为解决分类变量及混合型数据(数值+类别)的无监督聚类难题而设计,适用于客户分群、文本聚类、生物信息分析等实际场景。包内共30个文件,以20个核心Python源码(含kmodes.py、kprototypes.py及benchmark/示例脚本)、2个Markdown说明文档、2个CSV示例数据集(soybean.csv、stocks.csv)为主,辅以测试配置(.coveragerc)、构建脚本(setup.py)、许可证与README等,结构完整、开箱即用,压缩包仅36KB,轻量高效。已有2008人学习下载,资源包含从原理到实践的完整支撑:既有算法核心实现与scikit-learn风格API封装,也提供iris、soybean等经典数据集的端到端聚类示例,还涵盖并行加速、参数调优与评估指标应用等进阶内容,便于读者深入理解k-模式与k-原型算法差异,并快速迁移至真实业务数据建模。

1. 你手里的用户标签、商品类目、城市等级数据,根本跑不动KMeans——kmodes才是分类数据聚类的“原生解法”

上周帮某电商中台团队做用户分群,他们把「性别:男/女」、「会员等级:青铜/白银/黄金/钻石」、「常购品类:手机/美妆/母婴/家居」全转成数字(1/2/3/4)塞进sklearn.KMeans,结果轮廓系数只有0.12,聚类中心全是“2.73”这种玄学值,业务方盯着散点图直摇头:“这中心点我连读都读不出来,怎么定运营策略?”——问题不在模型调参,而在数据类型错配。KMeans本质是欧氏距离驱动的数值型算法,对分类变量强行编码后计算的距离毫无语义意义。kmodes专为离散型数据而生:它用模式(mode)代替均值,用汉明距离代替欧氏距离,聚类中心直接输出可读的类别组合,比如[男, 黄金, 手机]或[女, 青铜, 母婴]。它不依赖scikit-learn主库,但API设计高度兼容,fit()/predict()/cluster_centers_接口一模一样,老项目替换成本近乎为零。如果你的数据表里有超过3列是object或category类型(pandas里.dtypes一眼可见),别硬扛KMeans了——kmodes就是那把卡在分类数据锁孔里的原生钥匙。


2. 从pip install到跑通第一个demo:5分钟验证kmodes是否真能解决你的问题

2.1 安装与依赖:为什么不用改现有环境?

kmodes是纯Python实现,无C扩展,安装极轻量。它不依赖scikit-learn核心模块(只在可选的kprototypes中引用其部分工具函数),这意味着:

  • 你可以在隔离的conda env里单独安装,不影响线上KMeans流程;
  • 即使项目锁定scikit-learn==0.22.2(老版本不支持KPrototypes),kmodes仍可独立运行;
  • 它的底层距离计算全部用NumPy向量化,没有for循环黑匣子。
# 推荐:创建干净环境验证(避免包冲突) conda create -n kmodes-test python=3.8 conda activate kmodes-test pip install kmodes

提示:不要用pip install scikit-learn-kmodes——这是过时的第三方fork,官方维护的是kmodes(作者Nico Schlömer,GitHub star 1.2k+)。检查安装是否成功:

import kmodes print(kmodes.__version__) # 当前稳定版是0.12.2(2023年发布)

2.2 三行代码跑通分类数据聚类:用真实字段名重写示例

官方文档用['A','B','C']这种占位符,新手根本不知道怎么映射到自己数据。我们直接用电商场景的原始字段:

import pandas as pd from kmodes.kmodes import KModes # 假设你已加载数据:df.shape = (10000, 4) # columns: ['gender', 'member_level', 'preferred_category', 'region_tier'] df = pd.read_csv('user_profiles.csv') # 关键一步:确认所有列都是category或object,且无缺失(kmodes不处理NaN) print(df.dtypes) # gender object # member_level object # preferred_category object # region_tier object # 初始化KModes:n_clusters=4对应业务要求的“高/中/低价值+新客”四类 km = KModes(n_clusters=4, init='Huang', n_init=10, verbose=1) # fit!注意:传入的是.values(二维ndarray),不是DataFrame clusters = km.fit_predict(df.values) # 查看聚类中心——这才是人能看懂的规则! print("Cluster centers:") for i, center in enumerate(km.cluster_centroids_): print(f"Cluster {i}: {center}") # 输出示例: # Cluster 0: ['女' '钻石' '美妆' '一线'] # Cluster 1: ['男' '黄金' '手机' '新一线'] # Cluster 2: ['女' '青铜' '母婴' '三线及以下'] # Cluster 3: ['男' '白银' '家居' '二线']

逻辑说明:

  • init='Huang'是kmodes默认初始化策略(比随机初始化更稳定),n_init=10表示重复10次取最优解;
  • km.cluster_centroids_返回的是原始字符串组成的numpy array,不是编码后的数字,业务方能直接拿去写SQL或配置运营活动;
  • 如果你的数据含数值列(如age,order_count),不要强行塞进来——kmodes会报错或结果失真,下一章专门讲怎么和数值列共存。

2.3 评估聚类质量:别再只看轮廓系数

KMeans常用轮廓系数(silhouette score),但kmodes的汉明距离下该指标物理意义弱。更实用的三个指标:

指标计算方式业务解读kmodes内置支持
Cost(代价)所有样本到其簇中心的汉明距离之和数值越小越好,反映簇内紧凑度km.cost_属性直接获取
Dissimilarity(相异度)平均汉明距离(cost / 样本数)可跨不同n_clusters横向比较需手动计算:km.cost_ / len(df)
Cluster size distribution各簇样本数统计避免出现“1个样本独成一簇”的无效聚类pd.Series(clusters).value_counts().sort_index()
# 实战评估代码(加在fit_predict之后) print(f"Total cost: {km.cost_}") print(f"Mean dissimilarity: {km.cost_ / len(df):.3f}") cluster_sizes = pd.Series(clusters).value_counts().sort_index() print("\nCluster size distribution:") print(cluster_sizes) # 示例输出: # Cluster size distribution: # 0 3215 # 1 2890 # 2 2105 # 3 1790 # → 四簇分布较均衡,无极端偏斜

参数说明:

  • km.cost_是kmodes训练过程的核心收敛指标,每次迭代都会下降,最终值越小说明簇内一致性越高;
  • 若mean dissimilarity > 0.6(即平均每个样本有超60%的特征值与中心不一致),说明n_clusters可能设得太小,需增大尝试;
  • cluster_sizes小于总样本5%的簇要警惕——可能是噪声或参数不合理,需结合业务判断是否合并。

3. 核心模块拆解:一个请求从fit()进入到cluster_centroids_返回的完整链路

3.1 主流程入口:KModes.fit()如何调度整个聚类引擎

kmodes的fit()方法表面简洁,实则封装了三次关键跳转。我们跟踪源码(kmodes/kmodes.py第120行起):

def fit(self, X, y=None): # Step 1: 数据预处理(核心校验) X = self._check_array(X, dtype=None, accept_sparse=False) # 确保是2D ndarray if not np.array_equal(X, X.astype(object)): # 强制所有元素为object类型 raise TypeError("X must contain only categorical data.") # Step 2: 初始化簇中心(调用私有方法) self.cluster_centroids_, self.memberships_ = self._init_centroids( X, x_squared=None, random_state=self.random_state ) # Step 3: 迭代优化(核心!) for i in range(self.max_iter): # 3.1 分配样本到最近中心(汉明距离计算) self.memberships_ = self._e_step(X, self.cluster_centroids_) # 3.2 更新中心为各簇的众数(mode) new_centroids = self._m_step(X, self.memberships_) # 3.3 收敛判断:中心不再变化即停止 if np.array_equal(new_centroids, self.cluster_centroids_): self.n_iter_ = i + 1 break self.cluster_centroids_ = new_centroids return self

逻辑说明:

  • _check_array()不仅做形状校验,还强制类型转换为object,防止int/float混入——这是kmodes鲁棒性的第一道防线;
  • _e_step()是性能瓶颈所在:它对每个样本遍历所有中心,逐列比对字符串是否相等,累加不等列数(即汉明距离),时间复杂度O(n_samples × n_clusters × n_features),大数据量时建议先采样;
  • _m_step()的“众数计算”看似简单,实则处理了多众数(tie-breaking):当某特征在簇内出现频次相同时,kmodes默认取字典序最小的值(源码kmodes/util.py第87行),保证结果可重现。

3.2 汉明距离计算:为什么不用scipy.spatial.distance?

kmodes没调用任何现成距离库,而是手写向量化计算(kmodes/util.py第142行):

def get_max_value_frequency(X): """对每列计算众数及其频次""" modes = [] for j in range(X.shape[1]): col = X[:, j] values, counts = np.unique(col, return_counts=True) max_idx = np.argmax(counts) modes.append((values[max_idx], counts[max_idx])) return modes def hamming_distance(X, Y): """X: (n_samples, n_features), Y: (n_clusters, n_features)""" # 利用广播机制:X[:, None, :] vs Y[None, :, :] # 生成 (n_samples, n_clusters, n_features) 的布尔矩阵 diff_matrix = X[:, None, :] != Y[None, :, :] # 沿特征轴求和 → (n_samples, n_clusters) return np.sum(diff_matrix, axis=2)

参数说明:

  • X[:, None, :]是numpy的升维技巧,将样本矩阵从(n, f)变为(n, 1, f);
  • Y[None, :, :]将中心矩阵从(k, f)变为(1, k, f);
  • 布尔矩阵diff_matrix存储所有样本-中心对的逐特征相等性,np.sum(..., axis=2)即按特征维度累加不等次数;
  • 这种写法比双重for循环快10倍以上,但内存占用为O(n×k×f),若n=10^5, k=10, f=20,需1.6GB内存——这就是为什么大数据要先降维或采样。

3.3 簇中心更新:_m_step()如何安全计算众数

_m_step()是kmodes区别于其他聚类器的灵魂(kmodes/kmodes.py第280行):

def _m_step(self, X, memberships): """根据当前分配,更新每个簇的中心(众数)""" n_clusters = memberships.shape[1] n_features = X.shape[1] new_centroids = np.empty((n_clusters, n_features), dtype=object) for k in range(n_clusters): # 获取属于簇k的所有样本索引 k_indices = np.where(memberships[:, k])[0] if len(k_indices) == 0: # 空簇处理:随机选一个样本作为新中心(避免崩溃) new_centroids[k, :] = X[np.random.choice(len(X))] continue # 对簇k内所有样本的每一列,计算众数 for j in range(n_features): col_vals = X[k_indices, j] # 使用np.unique获取频次,取最高频次对应的值 values, counts = np.unique(col_vals, return_counts=True) max_count_idx = np.argmax(counts) new_centroids[k, j] = values[max_count_idx] return new_centroids

逻辑说明:

  • 空簇(empty cluster)是k-means类算法的通病,kmodes采用随机重置而非删除簇,保证n_clusters严格等于设定值;
  • np.unique(..., return_counts=True)是numpy最稳定的众数计算方式,比scipy.stats.mode更轻量且无额外依赖;
  • 注意new_centroids声明为dtype=object,确保字符串、数字、甚至元组都能存入——这是kmodes支持混合类型(如['A', 1, (1,2)])的基础。

4. 避坑指南:生产环境踩过的5个真实坑,附现象、原因与解决

4.1 现象:ValueError: X must contain only categorical data.

原因:数据中存在np.nan、None或数值型列(如int64),kmodes的_check_array()强制校验失败。
解决:

  • 先用df.isnull().sum()检查缺失值,用df.fillna('MISSING')统一填充(不能删行,否则破坏业务逻辑);
  • 对数值列执行df['age'] = df['age'].astype(str)转字符串(仅当业务允许时,如'25'代替25);
  • 更优方案:分离数值列,用kprototypes(kmodes的兄弟库)联合聚类,见第5章。

4.2 现象:聚类结果每次运行都不一样,cluster_centroids_内容随机变动

原因:init='random'且n_init=1(默认值),单次随机初始化导致结果不可复现。
解决:

  • 显式设置init='Huang'(论文提出者算法,稳定性远高于random);
  • 或固定随机种子:KModes(n_clusters=4, init='random', random_state=42, n_init=10);
  • 生产环境必须加random_state,这是血泪经验——某次AB测试因聚类漂移导致运营策略失效。

4.3 现象:MemoryError在hamming_distance()调用时爆发

原因:X样本量过大(>5万)且特征数多(>30),广播计算生成的(n, k, f)三维数组撑爆内存。
解决:

  • 降维:用pandas.get_dummies()做one-hot后,用sklearn.decomposition.TruncatedSVD压缩(保留95%方差);
  • 采样:df_sample = df.sample(n=10000, random_state=42),先验证参数再全量跑;
  • 分块计算:自定义_e_step,每次只计算1000个样本到中心的距离,用np.argmin()分批获取归属。

4.4 现象:某簇中心出现'MISSING',但业务上该字段本不该为空

原因:该簇内'MISSING'频次高于其他真实值(如'男'/'女'),被当作众数选中。
解决:

  • 预处理时用业务规则填充:df['gender'].fillna(df['gender'].mode()[0]),优先用众数而非固定值;
  • 聚类后人工审核:df[clusters==0]['gender'].value_counts(),若'MISSING'占比>30%,说明该簇数据质量差,应剔除或打标;
  • 进阶:在_m_step中加入权重,给'MISSING'赋0.1权重,真实值赋1.0权重(需修改源码)。

4.5 现象:fit_predict()耗时超30分钟,CPU使用率仅30%

原因:kmodes默认单线程,未利用多核。而汉明距离计算天然可并行。
解决:

  • 手动并行化_e_step:用joblib.Parallel拆分样本批次;
  • 更简单:换用kmodes的竞品caim(Categorical K-Means),它用Cython加速,速度提升5倍;
  • 或接受折中:n_init=1+max_iter=5,牺牲少量精度换速度(实测在电商数据上轮廓差异<0.02)。

5. 混合数据实战:当你的表里既有“性别”又有“消费金额”,kprototypes才是终极答案

5.1 为什么kmodes不能直接处理数值列?一个反例说明

假设用户数据含['gender', 'age', 'preferred_category']三列,你强行df.values传入kmodes:

# 错误示范! df_mixed = pd.DataFrame({ 'gender': ['男','女','男'], 'age': [25, 32, 41], # int64列 'category': ['手机','美妆','家居'] }) km = KModes(n_clusters=2) km.fit_predict(df_mixed.values) # 报错或结果荒谬

现象:age列被当作字符串'25'参与汉明距离计算,'25'和'32'的汉明距离是2(两个字符都不同),但25和32的实际数值距离是7——语义完全错乱。kmodes的设计哲学是“分类数据用汉明,数值数据用欧氏”,混合场景必须用kprototypes。

5.2 kprototypes安装与基础用法:API几乎零学习成本

kprototypes是kmodes作者同一团队开发,共享代码基,安装和调用无缝衔接:

pip install kprototypes # 注意:不是kmodes的一部分!
from kprototypes import KPrototypes # 关键:指定数值列索引(从0开始) # 假设df.columns = ['gender', 'age', 'category', 'region'] # 数值列是'age'(索引1),其余为分类列 numeric_columns = [1] # ← 唯一需要额外指定的参数 kp = KPrototypes(n_clusters=4, init='Huang', n_init=5, verbose=1) clusters = kp.fit_predict(df.values, categorical=[0,2,3]) # categorical参数指定分类列索引 # 聚类中心:分类列是字符串,数值列是float print(kp.cluster_centroids_) # 输出示例: # [ # ['女', 28.3, '美妆', '一线'], # ['男', 35.7, '手机', '新一线'], # ['女', 42.1, '母婴', '三线'], # ['男', 29.8, '家居', '二线'] # ]

逻辑说明:

  • categorical=[0,2,3]告诉kprototypes:第0、2、3列用汉明距离,第1列(age)用欧氏距离;
  • kp.cluster_centroids_返回混合类型数组,打印时数值列自动显示小数,分类列保持字符串;
  • 内部距离计算公式:total_distance = λ * hamming_dist + euclidean_dist,其中λ自动根据数据范围缩放,无需手动调参。

5.3 参数调优实战:如何让“年龄”和“性别”的贡献度平衡?

kprototypes默认自动缩放,但业务场景常需干预。例如:运营认为“年龄差5岁”比“性别不同”更重要,需加大age权重:

from sklearn.preprocessing import StandardScaler # 方案1:预处理数值列(推荐) scaler = StandardScaler() df_scaled = df.copy() df_scaled['age'] = scaler.fit_transform(df[['age']]) # 标准化后,age的std≈1 kp = KPrototypes(n_clusters=4, categorical=[0,2,3]) clusters = kp.fit_predict(df_scaled.values, categorical=[0,2,3]) # 方案2:手动指定gamma(距离权重系数) # gamma越大,数值列影响越强;默认gamma=0.5 kp = KPrototypes(n_clusters=4, categorical=[0,2,3], gamma=2.0)

参数说明:

  • gamma是kprototypes的核心调优参数,范围通常在0.1~10之间;
  • gamma=0.1:几乎只看分类列(适合“地域+品类”主导的场景);
  • gamma=5.0:数值列主导(适合“消费金额+浏览时长”关键的场景);
  • 验证方法:画gamma扫描图,横轴gamma,纵轴kp.cost_,选择cost下降趋缓的拐点。

6. 二次开发技巧:从“能跑”到“可控可解释”的3个改造点

6.1 改造点1:给聚类中心添加业务标签,告别Cluster 0这种编号

生产环境没人记得Cluster 2对应什么人群。我们在fit_predict()后注入业务逻辑:

# 定义业务标签映射(根据聚类中心内容动态生成) def generate_cluster_label(centroid): """输入:['女','钻石','美妆','一线'] → 输出:'高净值女性美妆客'""" gender, level, category, region = centroid level_map = {'青铜':'新客', '白银':'成长', '黄金':'主力', '钻石':'高净值'} region_map = {'一线':'核心', '新一线':'潜力', '二线':'稳健', '三线及以下':'下沉'} return f"{level_map[level]}{gender}{region_map[region]}{category}客" # 生成带标签的结果 labels = [generate_cluster_label(center) for center in kp.cluster_centroids_] df['cluster_label'] = pd.Series(clusters).map(dict(enumerate(labels))) # 输出可交付报表 report = df.groupby('cluster_label').agg({ 'age': ['mean', 'std'], 'order_count': 'sum', 'preferred_category': lambda x: x.mode()[0] if not x.mode().empty else 'N/A' }).round(2) print(report)

效果:报表直接输出高净值女性美妆客的平均年龄28.3、订单总数12500,运营同学拿到就能写方案,不用再查cluster_centroids_对照表。

6.2 改造点2:实现增量聚类,避免每天全量重训

kmodes不支持partial_fit(),但我们可以模拟增量逻辑:

class IncrementalKModes: def __init__(self, n_clusters=4, decay_factor=0.9): self.n_clusters = n_clusters self.decay_factor = decay_factor # 老数据权重衰减系数 self.centroids_ = None self.n_samples_ = 0 def partial_fit(self, X_new): if self.centroids_ is None: # 首次训练 km = KModes(n_clusters=self.n_clusters, init='Huang') self.centroids_ = km.fit(X_new).cluster_centroids_ self.n_samples_ = len(X_new) else: # 增量更新:用老中心初始化,只跑1次迭代 km = KModes(n_clusters=self.n_clusters, init=self.centroids_, n_init=1, max_iter=1) km.fit(X_new) # 加权融合:新数据占1份,老数据占decay_factor份 weight_new = len(X_new) weight_old = self.n_samples_ * self.decay_factor # 众数融合:对每列,合并新老数据的值频次后取众数 for j in range(X_new.shape[1]): # 合并新数据该列值 + 老中心该列值(按权重复制) all_vals = list(X_new[:, j]) + [self.centroids_[i,j] for i in range(self.n_clusters) for _ in range(int(weight_old/self.n_clusters))] self.centroids_[:, j] = pd.Series(all_vals).mode().iloc[0] self.n_samples_ = weight_new + weight_old # 使用 ikm = IncrementalKModes(n_clusters=4, decay_factor=0.95) ikm.partial_fit(df_day1.values) ikm.partial_fit(df_day2.values) # 每天只传当日新增数据

逻辑说明:

  • decay_factor=0.95表示老数据影响力每天衰减5%,7天后只剩70%;
  • 众数融合时,老中心值按权重复制,避免'MISSING'因权重高被误选;
  • 此方案比全量重训快10倍,且聚类中心平滑演进,不会出现某天突然“高净值客”变“新客”。

6.3 改造点3:可视化聚类可解释性,让业务方信服

kmodes输出的是离散中心,无法用PCA降维画图。我们用特征重要性热力图替代:

import seaborn as sns import matplotlib.pyplot as plt def plot_cluster_explainability(km_model, feature_names): """绘制各簇中心在各特征上的分布热力图""" centroids = km_model.cluster_centroids_ n_clusters, n_features = centroids.shape # 构建热力图数据:每簇每特征的“唯一值数量” # 值越小,说明该簇在该特征上越集中(越有区分度) uniqueness = np.zeros((n_clusters, n_features)) for i in range(n_clusters): for j in range(n_features): # 统计该簇中心在特征j上与其他簇的差异程度 other_vals = [centroids[k,j] for k in range(n_clusters) if k != i] uniqueness[i,j] = sum(centroids[i,j] != val for val in other_vals) plt.figure(figsize=(8, 6)) sns.heatmap(uniqueness, annot=True, fmt='.0f', xticklabels=feature_names, yticklabels=[f'Cluster {i}' for i in range(n_clusters)], cmap='Blues', cbar_kws={'label': 'Distinct from other clusters'}) plt.title('Cluster Differentiation Heatmap') plt.tight_layout() plt.show() # 调用 plot_cluster_explainability(kp, ['gender','age','category','region'])

效果:热力图中颜色越深(数字越大),表示该簇在该特征上越独特。例如Cluster 0在category列值为'美妆',而其他簇都是'手机'/'母婴',则uniqueness[0,2]=3(区别于全部3个其他簇),业务方一眼看出“美妆客”是独立群体。

从那以后我每次上线聚类模型,都强制走一遍这三步:1)用业务语言重命名簇;2)写增量更新脚本防漂移;3)画热力图给产品开会。不是为了炫技,而是让算法结论真正长进业务决策的毛细血管里。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 6:57:21

Melon Google Books Downloader:PDF提取与元数据结构化工具链

简介&#xff1a;Melon Google Books Downloader&#xff08;MGBD&#xff09;是一款面向研究者、学生及数字资源爱好者的小型桌面工具&#xff0c;专为合法获取Google Books平台上的预览内容而设计&#xff0c;解决用户无法直接下载整书PDF/EPUB的痛点&#xff0c;适用于文献调…

作者头像 李华
网站建设 2026/10/17 6:57:07

上位机CAN总线通讯DEMO:USB-CAN适配器报文收发与避坑指南

简介&#xff1a;一份面向嵌入式与工控开发者的上位机CAN总线通讯DEMO&#xff0c;演示如何构建PC端程序与CAN总线设备进行数据交互。程序基于C#开发&#xff0c;涵盖CAN协议解析、控制器驱动配置、报文收发、错误处理及简单界面展示等关键环节&#xff0c;适合正在学习CAN通讯…

作者头像 李华
网站建设 2026/10/17 6:57:04

希尔伯特空间入门:从内积、完备性到正交投影的几何直觉

1. 为什么偏要提"希尔伯特"&#xff1a;从欧氏空间带过去的直觉泛函分析这门课&#xff0c;学到第四章"希尔伯特空间"&#xff0c;很多人的第一反应是&#xff1a;这不就是内积空间吗&#xff1f;说得再细一点&#xff0c;不就是带完备性的内积空间吗&…

作者头像 李华
网站建设 2026/10/17 6:56:36

工厂涉外技术对接:专业翻译机为何能显著降低出错率

在涉外制造工厂的车间里&#xff0c;最让人头疼的往往不是设备故障或原料短缺&#xff0c;而是那些因沟通偏差导致的“隐形损失”。想象一下这样的场景&#xff1a;外方客户站在轰鸣的生产线旁&#xff0c;指着图纸上的一个参数急切地询问&#xff0c;而我们的技术人员拿着普通…

作者头像 李华
网站建设 2026/10/17 6:56:29

重磅:美八州起诉人工智能巨头,要求叫停核心算法自我改进

重磅&#xff1a;美八州起诉人工智能巨头&#xff0c;要求叫停核心算法自我改进 一个随时准备倾听、永远温和回应你的聊天软件&#xff0c;怎么会突然变成八个州总检察长联手围剿的对象&#xff1f; 2026年10月14日&#xff0c;美国八个州的总检察长几乎在同一时间&#xff0c;…

作者头像 李华