multi-view clustering指标

2023-11-12

几种 multi-view clustering 的指标代码,介绍见 [1-3],[4-6] 有实现。

Matching / Assignment

由于聚类没有类顺序,而有些指标用到 ground-truth labels(如 accuracy 等分类指标),需要求聚类簇跟 ground-truth 类之间的对应关系。

总体来说就是跑一个匹配算法求最优匹配,记 ground-truth labels y y yy_true、聚类模型输出的 cluster assignment y ′ y' yy_assign、匹配并调整顺序后的 assignment y ′ ′ y'' y′′y_adjust,都是 N n \N^n Nn 的一维向量,长度 n 是 instance 数。

cost matrix

算匹配之前,要求一个 cost 矩阵 W,在此之前先求一个 co-occurrence 矩阵(临时起的名 C ∈ N d × c C\in \N^{d \times c} CNd×c C i j = ∣ { k ∣ y k ′ = i ∧ y k = j , k = 1 , … , n } ∣ C_{ij}=\left|\{k|y'_k=i\wedge y_k=j, k=1,\dots,n\}\right| Cij={kyk=iyk=j,k=1,,n} 其中 c 是 ground-truth 类数,d 是聚类簇数,MVC 里一般 c = d。然后 W i j = m − C i j , m = max ⁡ r , c C r c W_{ij}=m - C_{ij}, \quad m = \max_{r,c} C_{rc} Wij=mCij,m=r,cmaxCrc

有些数据集的 y_true 的 class ID 是从 0 开始,以这里假设 class ID、cluster ID 都是从 0 开始。

# import numpy as np

def calc_cost_matrix(y_true, y_assign, n_classes, n_clusters):
    """calculate cost matrix W
    Input:
        y_true: [n], in {0, ..., n_classes - 1}
        y_assign: [n], in {0, ..., n_clusters - 1}
        n_classes: int, provide in case that y_true.max() != n_classes
        n_clusters: int, provide in case that y_assign.max() != n_clusters
    Output:
        W: [n_clusters, n_classes]
    """
    y_true = y_true.astype(np.int64)
    y_assign = y_assign.astype(np.int64)
    assert y_assign.size == y_true.size # n
    # C = np.zeros((y_assign.max() + 1, y_true.max() + 1), dtype=np.int64)
    C = np.zeros((n_clusters, n_classes), dtype=np.int64)
    for i in range(y_assign.size):
        C[y_assign[i], y_true[i]] += 1
    W = C.max() - C
    return W

munkres

[4] 用 munkres 包求,代码在 get_y_preds

# import numpy as np
# from munkres import Munkres

def reorder_assignment(y_true, y_assign, n_classes, n_clusters):
    """(munkres) re-order y_assign to be y_adjust so that it has the same order as y_true
    Input:
        y_true: [n], in {0, ..., c - 1}
        y_assign: [n], in {0, ..., d - 1}
        n_classes: int, provide in case that y_true.max() != n_classes
        n_clusters: int, provide in case that y_assign.max() != n_clusters
    Output:
        y_adjust: [n], in {0, ..., c - 1}, in same order as y_true
    """
    W = calc_cost_matrix(y_true, y_assign, n_classes, n_clusters)
    indices = Munkres().compute(W)
    map_a2t = np.zeros(n_clusters, dtype=np.int64)
    for i in range(n_clusters):
        map_a2t[i] = indices[i][1]
    y_adjust = map_a2t[y_assign]
    return y_adjust

linear_sum_assignment

[5,6] 用 scipy.optimize.linear_sum_assignment 求,代码分别在 cluster_accordered_cmat;[7] 也有示例。

# import numpy as np
# from scipy.optimize import linear_sum_assignment

def reorder_assignment(y_true, y_assign, n_classes, n_clusters):
    """(linear_sum_assignment) re-order y_assign to be y_adjust so that it has the same order as y_true
    Input:
        y_true: [n], in {0, ..., c - 1}
        y_assign: [n], in {0, ..., d - 1}
        n_classes: int, provide in case that y_true.max() != n_classes
        n_clusters: int, provide in case that y_assign.max() != n_clusters
    Output:
        y_adjust: [n], in {0, ..., c - 1}, in same order as y_true
    """
    W = calc_cost_matrix(y_true, y_assign, n_classes, n_clusters)
    row_idx, col_idx = linear_sum_assignment(W)
    map_a2t = np.zeros(n_clusters, dtype=np.int64)
    for i, j in zip(row_idx, col_idx):
        map_a2t[i] = j
    y_adjust = map_a2t[y_assign]
    return y_adjust

Clustering Metrics

这里区分「聚类」指标和「分类」指标,这一节聚类指标指需重排 cluster assignment 以对齐 ground-truth label 顺序的指标。

purity

介绍见 [1,2],范围 [0, 1],越大越好。[5] 有实现:purity

# import numpy as np
# from sklearn.metrics import accuracy_score

def purity(y_true, y_assign):
    y_voted_labels = np.zeros(y_true.shape)
    labels = np.unique(y_true)
    ordered_labels = np.arange(labels.shape[0])
    for k in range(labels.shape[0]):
        y_true[y_true == labels[k]] = ordered_labels[k]
    labels = np.unique(y_true)
    bins = np.concatenate((labels, [np.max(labels)+1]), axis=0)

    for cluster in np.unique(y_assign):
        hist, _ = np.histogram(y_true[y_assign == cluster], bins=bins)
        winner = np.argmax(hist)
        y_voted_labels[y_assign == cluster] = winner

    return accuracy_score(y_true, y_voted_labels)

NMI

Normalized mutual information,介绍见 [1,3],范围 [0, 1],越大越好。[4,6] 用 sklearn.metrics.normalized_mutual_info_scoreclustering_metriccalc_metrics),[5] 用 sklearn.metrics.v_measure_scoreevaluate)。

  • 关于 v_measure_score,scikit-learn 说:This score is identical to normalized_mutual_info_score with the ‘arithmetic’ option for averaging.
# from sklearn.metrics import normalized_mutual_info_score, v_measure_score

def nmi(y_true, y_assign):
    # return v_measure_score(y_true, y_assign)
    return normalized_mutual_info_score(y_true, y_assign)

AMI

Adjusted mutual information,介绍见 [3],范围 [-1, 1],越大越好。[4] 用 sklearn.metrics.adjusted_mutual_info_score,见 clustering_metric

# from sklearn.metrics import adjusted_mutual_info_score

def ami(y_true, y_assign):
    return adjusted_mutual_info_score(y_true, y_assign)

ARI

Adjusted Rand index,介绍见 [1-3],范围 [-1, 1],越大越好。[4,6] 用 sklearn.metrics.adjusted_rand_score,见 clustering_metriccalc_metrics

# from sklearn.metrics import adjusted_rand_score

def ari(y_true, y_assign):
    return adjusted_rand_score(y_true, y_assign)

Classification Metrics

这一节的分类指标指重排 assignment 得到 y_adjust 的指标。

ACC

Accuracy,范围 [0, 1],越大越好。[4] 用 sklearn.metrics.accuracy_score,[5,6] 手写,分别见 classification_metriccluster_accordered_cmat

# from sklearn.metrics import accuracy_score

def acc(y_true, y_adjust):
    return accuracy_score(y_true, y_adjust)

precision

范围 [0, 1],越大越好。[4] 用 sklearn.metrics.precision_score,见 classification_metric

# from sklearn.metrics import precision_score

def precision(y_true, y_adjust, average='macro'):
    return precision_score(y_true, y_adjust, average=average)

recall

范围 [0, 1],越大越好。[4] 用 sklearn.metrics.recall_score,见 classification_metric

# from sklearn.metrics import recall_score

def recall(y_true, y_adjust, average='macro'):
    return recall_score(y_true, y_adjust, average=average)

f1-score

范围 [0, 1],越大越好。[4] 用 sklearn.metrics.f1_score,见 classification_metric

# from sklearn.metrics import f1_score

def f1_score(y_true, y_adjust, average='macro'):
    return f1_score(y_true, y_adjust, average=average)

Combination

写在一起方便调用

# evaluate.py
import numpy as np
from scipy.optimize import linear_sum_assignment
import sklearn.metrics as metrics


def calc_cost_matrix(y_true, y_assign, n_classes, n_clusters):
    """calculate cost matrix W
    Input:
        y_true: [n], in {0, ..., n_classes - 1}
        y_assign: [n], in {0, ..., n_clusters - 1}
        n_classes: int, provide in case that y_true.max() != n_classes
        n_clusters: int, provide in case that y_assign.max() != n_clusters
    Output:
        W: [n_clusters, n_classes]
    """
    y_true = y_true.astype(np.int64)
    y_assign = y_assign.astype(np.int64)
    assert y_assign.size == y_true.size # n
    # C = np.zeros((y_assign.max() + 1, y_true.max() + 1), dtype=np.int64)
    C = np.zeros((n_clusters, n_classes), dtype=np.int64)
    for i in range(y_assign.size):
        C[y_assign[i], y_true[i]] += 1
    W = C.max() - C
    return W


def reorder_assignment(y_true, y_assign, n_classes, n_clusters):
    """(linear_sum_assignment) re-order y_assign to be y_adjust so that it has the same order as y_true
    Input:
        y_true: [n], in {0, ..., c - 1}
        y_assign: [n], in {0, ..., d - 1}
        n_classes: int, provide in case that y_true.max() != n_classes
        n_clusters: int, provide in case that y_assign.max() != n_clusters
    Output:
        y_adjust: [n], in {0, ..., c - 1}, in same order as y_true
    """
    W = calc_cost_matrix(y_true, y_assign, n_classes, n_clusters)
    row_idx, col_idx = linear_sum_assignment(W)
    map_a2t = np.zeros(n_clusters, dtype=np.int64)
    for i, j in zip(row_idx, col_idx):
        map_a2t[i] = j
    y_adjust = map_a2t[y_assign]
    return y_adjust


def purity(y_true, y_assign):
    y_voted_labels = np.zeros(y_true.shape)
    labels = np.unique(y_true)
    ordered_labels = np.arange(labels.shape[0])
    for k in range(labels.shape[0]):
        y_true[y_true == labels[k]] = ordered_labels[k]
    labels = np.unique(y_true)
    bins = np.concatenate((labels, [np.max(labels)+1]), axis=0)

    for cluster in np.unique(y_assign):
        hist, _ = np.histogram(y_true[y_assign == cluster], bins=bins)
        winner = np.argmax(hist)
        y_voted_labels[y_assign == cluster] = winner

    return metrics.accuracy_score(y_true, y_voted_labels)


def evaluate(y_true, y_assign, n_classes, n_clusters, average='macro'):
    y_adjust = reorder_assignment(y_true, y_assign, n_classes, n_clusters)
    return {
        # clustering
        'purity': purity(y_true, y_assign),
        'nmi': metrics.normalized_mutual_info_score(y_true, y_assign),
        'ami': metrics.adjusted_mutual_info_score(y_true, y_assign),
        'ari': metrics.adjusted_rand_score(y_true, y_assign),
        # classification
        'acc': metrics.accuracy_score(y_true, y_adjust),
        'precision': metrics.precision_score(y_true, y_adjust, average=average),
        'recall': metrics.recall_score(y_true, y_adjust, average=average),
        'f1-score': metrics.f1_score(y_true, y_adjust, average=average)
    }

References

  1. [ML] 聚类评价指标
  2. 几种常见的聚类外部评价指标
  3. 十分钟掌握聚类算法的评估指标
  4. XLearning-SCU/2021-CVPR-Completer
  5. Gasteinh/DSIMVC
  6. DanielTrosten/DeepMVC
  7. 利用python解决指派问题(匈牙利算法)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

multi-view clustering指标 的相关文章

随机推荐

  • 实战--Kafka学习(二)

    问题导读1 Kafka工作包含哪些流程 2 为防止log文件过大导致数据定位效率低下 kafka引入了什么 3 Kafka生产者分区的原因和原则是什么 4 Kafka数据可靠性是如何保证的 3 1 Kafka工作流程及文件存储机制Kafka
  • 哈希及其应用(字典,加密等)

    一 名词说明 Hash 一般翻译做散列 杂凑 或音译为哈希 是把任意长度的输入 又叫做预映射pre image 通过散列算法变换成固定长度的输出 该输出就是散列值 这种转换是一种压缩映射 也就是 散列值的空间通常远小于输入的空间 不同的输入
  • kafka学习

    链接1 Kafka入门教程 香菜 的博客 CSDN博客 链接2 https mbd baidu com ug share mbox 4a83aa9e65 share product smartapp tk d716b5f663babe030
  • mysql函数及关键字使用

    collect set collect set col 函数只接受 基本数据类型 它的主要作用是将某字段的值进行去重汇总 产生array类型字段 MySQL中concat函数 连接字符串 MySQL中concat函数 使用方法 concat
  • java语法基础练习

    1 阅读示例 EnumTest java 并运行 分析结果 代码 public class EnumTest public static void main String args Size s Size SMALL Size t Size
  • MSP432学习笔记:IAR的环境配置(官方demo程序的测试)

    近来入手一块MSP432 折腾了一天 终于把官方demo程序导入IAR 可以愉快的写代码了 以下是我个人的解决办法 首先 如果要使用IAR对TI的单片机进行开发 首先要下载对应的单片机型号的MSPWARE 本人目前使用的是TI的MSP432
  • python实现的一些方法,可以直接拿来用的那种

    1 日期生成 很多时候我们需要批量生成日期 方法有很多 这里分享两段代码 获取过去 N 天的日期 import datetime def get nday list n before n days for i in range 1 n 1
  • 梯度下降算法

    下面这篇文章讲的非常不错 https www jianshu com p c7e642877b0e 转载于 https www cnblogs com lvchaoshun p 11403808 html
  • 【网络】协议定制+序列化/反序列化

    为什么要序列化 如果光看定义很难理解序列化的意义 那么我们可以从另一个角度来推导出什么是序列化 那么究竟序列化的目的是什么 其实序列化最终的目的是为了对象可以跨平台存储 和进行网络传输 而我们进行跨平台存储和网络传输的方式就是IO 而我们的
  • leetcode刷题(5)

    各位朋友们 大家好 今天是我leedcode刷题的第五篇 我们一起来看看吧 文章目录 栈的压入 弹出序列 题目要求 用例输入 提示 做题思路 代码实现 C语言代码实现 Java代码实现 最小栈 题目要求 用例输入 提示 做题思路 代码实现
  • eclipse中使用Install New software下载资源超时解决

    问题 使用eclipse中提供的Help菜单 Install New software 已填入正确的链接地址 但是在下载过程中出现错误 Some sites could not be found See the error log for
  • 宝塔面板升级踩坑:ImportError: class/PluginLoader.so: undefined symbol: PyImport_GetModule

    今天在宝塔面板升级了PHP8 但是站点的PHP版本选择仍然没有PHP8以上的版本 百度了一下说是要升级宝塔面板 于是在面板首页右上角进行了升级 结果升级后发现安全入口无法打开 于是用ssh登录服务器 执行命令 etc init d bt d
  • 推荐 20 款 IDEA 主题!

    官方对主题模块的介绍 作为一名开发人员 您需要使用大量文本资源 编辑器中的源代码 搜索结果 调试器信息 控制台输入和输出等等 颜色和字体样式用于格式化这个文本 并帮助您更好地理解它一目了然 个人感觉 每天我们大半的时间都是在跟代码打交道 时
  • Vue前端代码风格指南超级详细

    本文仅作日常项目开发中的知识补充 不必按顺序阅读 如果已经知悉 请跳过 一 命名规范 现有常用的命名规范 camelCase 小驼峰 首字母小写 PsscalCase 大驼峰 首字母大写 kebab case 短横线连接式 Snake 下划
  • VSCode好用的插件

    文章目录 前言 1 Snippet Creator easy snippet 自定义代码 2 Indent Rainbow 代码缩进 3 Chinese Simplified Language Pack 中文包 4 Path Intelli
  • react项目配置 @ 为src根目录

    前置 修改jsconfig json文件 compilerOptions jsx react experimentalDecorators true baseUrl paths src 1 原生create react app 的情况 若已
  • 16、什么是拟牛顿法(Quasi-Newton Methods)?

    拟牛顿法是求解非线性优化问题最有效的方法之一 于20世纪50年代由美国Argonne国家实验室的物理学家W C Davidon所提出来 Davidon设计的这种算法在当时看来是非线性优化领域最具创造性的发明之一 不久R Fletcher和M
  • CSharp: iTextSharp 5.13.2 create pdf

    using System using System Collections Generic using System Web using System Web UI using System Web UI WebControls using
  • 超级卡哇伊的登录框

    css margin 0 padding 0 box sizing border box a color 6a6a6a text decoration none body background color 96c6e2 box displa
  • multi-view clustering指标

    几种 multi view clustering 的指标代码 介绍见 1 3 4 6 有实现 Matching Assignment 由于聚类没有类顺序 而有些指标用到 ground truth labels 如 accuracy 等分类指