Google Research 的 MSEB 編碼指南:依照基準契約撰寫健全的編碼器,並在分類、聚類、檢索與分割任務中評分

2026年9月27日 05:42
站內 AI 整理稿

In this tutorial, we work with MSEB, the Massive Sound Embedding Benchmark from Google Research, and approach it from the perspective of what a leaderboard number actually means: the evaluator surface.

We install the package and map its three layers, then write two deliberately different encoders against the framework’s own abstract base class: one that measures loudness over time and one that measures timbre, and encode a small synthetic corpus we generate in the notebook so nothing has to be downloaded.

We drive the classification, clustering, retrieval, and segmentation evaluators over those embeddings, call the metric functions directly to see what each one rewards, and finish by assembling the TaskMetadata a real submission carries.

The result is a comparison in which the two encoders trade places depending on which evaluator is asked, which is the argument for a multi-task benchmark made in numbers rather than in prose.

Copy CodeCopiedUse a different Browserimport os import sys import json import math import traceback import subprocess import numpy as np RESULTS = {} BENCH = {} def banner(title): print("\n" + "=" 78) print(title) print("=" 78) def section(name): def wrap(fn): def run(a, kw): banner(name) try: out = fn(a, kw) RESULTS[name] = out if isinstance(out, str) else "ok" return out except Exception as e: RESULTS[name] = f"SKIPPED / FAILED -> {type(e).

name}: {e}" print(f"\n[!] {name} did not complete: {type(e).name}: {e}") traceback.printexc(limit=3) return None return run return wrap banner("0.Install MSEB and map the three layers we will use") subprocess.run([sys.executable, "-m", "pip", "install", "-q", "mseb==0.1.

0"], check=True) import mseb from mseb import types, encoder as encoderlib, evaluator as evaluatorlib, metrics from mseb.evaluators import ( classificationevaluator, clusteringevaluator, retrievalevaluator, segmentationevaluator, ) print(f" mseb {mseb.version} | Python {sys.version.

split()[0]} | numpy {np.

version}") print("\n MSEB is three layers, and a benchmark run walks down them:") print(" types -> Sound, SoundEmbedding, Score, TaskMetadata: the shapes every task speaks") print(" encoder -> MultiModalEncoder: the contract YOUR model implements") print(" evaluators -> classification, clustering, retrieval, reranking, transcription, segmentation, ...

") print("\n evaluator entry points we will drive:") for module, cls in [(classificationevaluator, "ClassificationEvaluator"), (clusteringevaluator, "ClusteringEvaluator"), (retrievalevaluator, "RetrievalEvaluator"), (segmentationevaluator, "SegmentationEvaluator")]: print(f" {module.name.split('.

')[-1]:28s} {cls}") print("\n Everything below runs on CPU with no dataset download: we synthesise the audio.") We install mseb and import the three layers that a benchmark run walks down.

The types module holds the shapes every task speaks, Sound, SoundEmbedding, Score and TaskMetadata; the encoder module holds MultiModalEncoder, the contract our own model implements; and the evaluators package holds one module per task family.

We import only the four evaluators this notebook drives, because the classification, clustering, retrieval, and segmentation modules depend on nothing heavier than NumPy and scikit-learn.

In contrast, the reranking and transcription evaluators pull in Whisper and the task runner pulls in TensorFlow and apache-beam.Everything below therefore runs on a free CPU runtime with no dataset download and no accelerator.Copy CodeCopiedUse a different BrowserSR = 16000 @section("1.

The type contract: Sound, SoundEmbedding, Score") def typecontract(): t = np.arange(SR) / SR waveform = (0.5 np.sin(2 np.pi 440 t)).astype(np.float32) sound = types.Sound( waveform=waveform, context=types.

SoundContextParams(id="demo000", samplerate=SR, length=len(waveform), language="enus", text="a 440 Hz tone"), ) print(f" Sound id={sound.context.id!r} {sound.waveform.shape} @ {sound.context.samplerate} Hz" f" -> {sound.sizebytes:,} bytes") embedding = types.SoundEmbedding( embedding=np.

zeros((1, 16), dtype=np.float32), # (N, D): one utterance-level vector timestamps=np.array([[0.0, 1.0]], dtype=np.float32), # (M, 2): [start, end] in seconds context=sound.context, encodingstats=types.EncodingStats(inputsizebytes=sound.

sizebytes, embeddingsizebytes=16 * 4), ) print(f" SoundEmbedding embedding{embedding.embedding.shape} timestamps{embedding.timestamps.shape}" f" -> {embedding.sizebytes} bytes") print(f" compressionratio = {embedding.encodingstats.compressionratio:.5f}" f" ({1 / embedding.encodingstats.

compressionratio:,.0f}x smaller than the audio)") print(" N embeddings and M timestamps: M == N is frame-aligned, M == 1 is utterance-level.") print(" embedding may also hold N strings instead of vectors - step 8 uses exactly that.") score = types.

Score(metric="Accuracy", description="Overall classification accuracy", value=0.875, min=0.0, max=1.0) print(f"\n Score {score.metric}={score.value} in [{score.min}, {score.max}] :: {score.description}") for bad, why in [(dict(metric="", description="d", value=0.5, min=0.0, max=1.

0), "empty metric name"), (dict(metric="m", description="d", value=0.5, min=1.0, max=0.0), "min > max")]: try: types.Score(bad) except Exception as e: print(f" rejected at construction ({why}): {type(e).name}: {e}") return f"Sound {sound.sizebytes:,} B -> embedding {embedding.

sizebytes} B" typecontract() We start with the type contract, because every other layer is expressed in it.A Sound carries a waveform, along with SoundContextParams, the identifier, sample rate, length, language, and optional transcript, which follow the audio through the whole pipeline.

A SoundEmbedding carries an array of N embeddings and an array of M timestamp pairs, and the relation between N and M is the benchmark’s vocabulary: M equal to N means one vector per frame, while M equal to one means a single utterance-level vector, which is what our encoders produce.

EncodingStats records the input and embedding sizes and exposes compressionratio, here a thousandfold reduction from audio to vector.

A Score is a metric name, a value and its bounds, and it validates itself at construction, rejecting an empty metric name or a minimum above its maximum, so a malformed number cannot reach a leaderboard.

The embedding field also accepts N strings instead of N vectors, which is the door that step 8 walks through.Copy CodeCopiedUse a different Browserclass EnergyEnvelopeEncoder(encoderlib.MultiModalEncoder): """Baseline: average energy in nbins equal time slices.Loud/quiet, nothing about timbre.

""" def init(self, nbins: int = 16): super().init() self.nbins = nbins def setup(self): self.ready = True # a real encoder loads weights here def checkinputtypes(self, batch): for item in batch: if not isinstance(item, types.Sound): raise ValueError(f"{type(self).name} takes types.

Sound, got {type(item).name}") def encode(self, batch) -> list[types.SoundEmbedding]: out = [] for sound in batch: slices = np.arraysplit(sound.waveform.astype(np.float32), self.nbins) vec = np.array([[float(np.sqrt(np.mean(s 2) + 1e-12)) for s in slices]], dtype=np.float32) vec /= np.linalg.

norm(vec) + 1e-9 out.append(types.SoundEmbedding( embedding=vec, timestamps=np.array([[0.0, sound.context.length / sound.context.samplerate]], dtype=np.float32), context=sound.context)) return out class SpectralProfileEncoder(encoderlib.

MultiModalEncoder): """Contender: mean log-magnitude spectrum pooled into nbands bands.Describes timbre.""" def init(self, nbands: int = 16, frame: int = 512): super().init() self.nbands, self.frame = nbands, frame def setup(self): self.window = np.hanning(self.frame).astype(np.

float32) def checkinputtypes(self, batch): for item in batch: if not isinstance(item, types.Sound): raise ValueError(f"{type(self).name} takes types.Sound, got {type(item).name}") def encode(self, batch) ->

Related

相關文章

北京互聯網法院:平臺誤判AI生成內容未標識構成違約

法院最終認定平臺構成違約,判決解除對涉案內容的隱藏並刪除後臺相應違規處理記錄。案件源於平臺要求創作者對AI生成內容主動添加標識。北京互聯網法院立案庭法官高雅介紹,被告以機器識別及人工複核認定涉案回答為AI生成內容,並以涉及技術秘密和算法邏輯為由主張無須向用戶解釋認定機制。

14 小時前
MarkTechPost AI研究與前沿

Meta FAIR 發布 e-means:以十分之一 epoch 數擊敗 k-means 的新演算法

Meta FAIR 研究人員發布了 e-means,這是 Lloyd 的 k-means 演算法的直接替代方案。e-means 聚類演算法只需 1.4 至 2.6 個 epoch,即可達到 Lloyd 的 k-means 在 25 個 epoch 時獲得的損失。該演算法已收錄於 FAISS 1.16.0 的 faiss.contrib.e_means 模組中。對於任何建構向量索引、量化器或資料整理管線的開發者而言,聚類通常是離線步驟中最耗時的一環,而 e-means 正是針對這一步驟進行最佳化。重點摘要:規模——這是一個演算法,已在 10 萬至 100 億個資料點、最高 1,670 萬個聚類中心的情況下測試。運行環境——支援 CPU 或 GPU,可使用 PyTorch 張量或 NumPy。論文中的 GPU 運行使用 H100。效能——在 24 種資料集配置下(自行報告),以約十分之一的 epoch 數達到比 Lloyd 的 k-means 更低的損失。最佳表現——在相同損失下,相較 Flash-KMeans 可獲得 10 至 45 倍的 GPU 實際運行加速。最差情況——1,600 萬個聚類中心(原文未完整,但此處指最差情境)。

23 小時前

雷軍曬小米機器人做家務視頻,Xiaomi-Robotics-1支撐長程任務

該機器人在小米青年公寓試運營,可完成垃圾清掃、物品分類歸位等家務任務,視頻中清掃瓜子殼、收拾遺落手機充電器等場景引發網友關注。這套機器人依託Xiaomi-Robotics-1具身基座模型,搭建完整自動執行系統,實測能夠連續運行超30分鐘、覆蓋3個房間、完成50+任務的長程任務驗證。

6 天前5100

追覓科技亮相2026世界互聯網大會人工智能嘉年華,以AI技術創新賦能智慧生活

11月2日,2026年世界互聯網大會烏鎮峰會在浙江嘉興烏鎮正式啟幕。本屆峰會以“開源開放、共建共享”為主題,聚焦人工智能等前沿技術發展與產業應用。追覓攜旗下T70 Ultra Station、T60 Steam等多款旗艦洗地機亮相“人工智能嘉年華”展區,集中展示智能清潔領域的技術創新成果,呈現前沿科技與家庭生活深度融合的創新實踐。作為全球領先的智能科技品牌,追覓始終堅持以技術創新驅動產品升級,持續探索人工智能、智能感知與清潔技術的融合應用。此次亮相的追覓T70 Ultra Station洗地機,集成多項行業首創技術,以創新設計進一步拓展家庭清潔的場景邊界。其中,首創的EdgeHunter巡邊探洗臂搭載高精度TOF測距傳感器與新一代具身智能算法,可針對不同沿邊清潔場景實現5mm自動外擴和30mm手動外擴,有效突破傳統洗地機在牆邊、傢俱邊緣等區域的清潔侷限。同時,產品採用9.85cm超薄機身設計,支持180°恆動平躺清潔,可深入沙發、床底等低矮空間,進一步提升家庭清潔的覆蓋範圍與靈活性。從精準感知到智能決策,從核心技術突破到清潔場景創新,追覓持續推動智能科技向實際生活場景落地。目前,追覓聚焦智能家庭、戶外庭院、智能出行、具身智能四大核心賽道,推動前沿技術跨領域融合,並通過人性化設計與產品體驗創新,讓科技更好地融入日常生活。持續的技術創新也推動追覓全球業務穩步發展。目前,追覓產品與服務已覆蓋全球190餘個國家和地區,擁有超過13000家實體門店,累計服務超4200萬戶家庭。IDC數據顯示,2026年上半年,追覓掃地機器人全球銷量份額和銷售額份額均位居全球第一。未來,追覓將繼續深耕核心技術,推動人工智能與智能清潔技術深度融合,以創新產品和解決方案賦能全球家庭智慧生活。

1 週前