1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | import sys
from collections import defaultdict
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
import torchaudio
sys.path.append("speechbrain")
from speechbrain.inference import EncoderClassifier
def make_colormap(label_list, min_count):
color_map = defaultdict(int)
for label in label_list:
color_map[label] += 1
color_map_sorted = []
for k, v in color_map.items():
color_map_sorted.append((v, k))
color_map_sorted = reversed(sorted(color_map_sorted))
colors = ["b", "g", "r", "c", "m", "y", "k", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"]
cindex = 0
for v, k in color_map_sorted:
if v < min_count:
color_map[k] = None
continue
color_map[k] = colors[cindex] if cindex < len(colors) else "grey"
cindex += 1
color_list = []
for i in range(len(label_list)):
color_list.append(color_map[label_list[i]])
return color_list
def main(wav_list):
ec = EncoderClassifier.from_hparams(
source="speechbrain/spkrec-ecapa-voxceleb",
savedir="cache",
run_opts={"device": "cuda"},
use_auth_token=False
)
ec.hparams.label_encoder.ignore_len()
embed_list = []
label_list = []
with open(wav_list) as wavs:
i = 0
for line in wavs:
i += 1
line = line.strip()
signal, fs = torchaudio.load(line)
assert fs == 16000
# Get a speaker vector
embed_list.append(ec.encode_batch(signal, wav_lens=None).squeeze(dim=1).cpu().numpy())
label_list.append(line.split("/")[1].split("_")[0]) # Get speaker name
if i % 100 == 0:
print(i)
label_list = make_colormap(label_list, min_count=100)
# Filter speaker vectors
embed_list = [embed_list[i] for i in range(len(label_list)) if label_list[i] is not None]
label_list = [label_list[i] for i in range(len(label_list)) if label_list[i] is not None]
embed_list = np.concatenate(embed_list)
tsne = TSNE(n_components=2, random_state=123)
vec_2d = tsne.fit_transform(embed_list)
plt.figure(figsize=(10, 8))
plt.scatter(vec_2d[:,0], vec_2d[:,1], alpha=0.7, c=label_list)
plt.title("t-SNE visualization of speaker vectors")
plt.xlabel("t-SNE feature 1")
plt.ylabel("t-SNE feature 2")
plt.grid(True, linestyle="--", alpha=0.7)
plt.savefig("spk_distribution.png", dpi=300, bbox_inches="tight")
plt.close()
if __name__ == "__main__":
main("audio-16k.list")
|
~ただのメモ置き場。なので、内容の正しさについての保証は一切ありませんよ~ copyright (c) 2006-2025 bluewidz, all rights reserved.
2024/07/14
話者ベクトル
話者ベクトルをhttps://github.com/speechbrain/speechbrain.gitで取得してみます。
話者ベクトルの計算にはEncoderClassifier.encode_batchを使います。サンプリング周波数16kHzの音声データをこの関数に入力すると話者ベクトルが得られます。
それ以外の部分は音声の読み込みとt-SNEによる2Dベクトル化、散布図描画のための色の選択と、散布図の作成をしているだけです。
35行目でEncoderClassifierを作成して、52行目で話者ベクトルを取得します。
audio-16k.listは1行ごとに.wavファイルへのパスが書かれていることを想定しています。
実行すると、以下のような散布図が得られます。少し混じっているところはあるものの、色ごとに、つまり話者ごとにクラスタが異なっていることが分かります。
2024/07/06
moreの挙動が変化した
Debianを11から12にアップグレードしたところ、moreコマンドのデフォルトの挙動が変化しました。
具体的には、表示するテキストの行が画面の行数よりも短いときは、単にcatで出力される状態であったのに、画面をクリアして画面の上部に表示されるようになりました。
lessでいうと、less -Fの挙動をしていたものが、less -cに似た挙動に変更されてしまいました。しかも、元の画面を削除して復旧しないという挙動です。
less -Fが手間なのでmoreを使っていたのに、これは困ったことになってしまいました。
Perplexityによると
Linuxのmoreコマンドの動作変更は、util-linux パッケージのバージョン2.38で導入されました。この変更により、表示する内容が端末の画面高さよりも少ない行数の場合でも、画面の上部から表示されるようになりました。 この変更は、より一貫性のある動作を提供し、ユーザーエクスペリエンスを向上させることを目的としています。以前のバージョンでは、内容が短い場合に画面の下部に表示されることがあり、これが一部のユーザーにとって混乱を招く原因となっていました。 util-linux 2.38は2022年4月にリリースされており、この版で上記の動作変更が実装されました。したがって、util-linux 2.37.2と2.38.1の間で発生したこの変更は、正確には2.38で導入されたものです。とのこと。 moreコマンドが含まれているlinux-utilのバージョンは、Debian 11では2.36.1、Debian 12では2.38.1です。また、Ubuntu 22.04のmoreはDebian 11と挙動が同じで、そのバージョンは2.37.2です。 そこで、linux-utilのログを調べてみると、
2021-06-01 build-sys: release++ (v2.37)v2.37 2022-01-31 build-sys: release++ (v2.38-rc1)v2.38-rc1 2022-03-28 build-sys: release++ (v2.38)v2.38でした。これらの間のどこかに変更が含まれているはずです。 調べてみると
commit df6b29d3b8e9a55d2bfa69c593e17da4d11a3fac
AuthorDate: Wed Sep 29 14:50:14 2021 +0200
CommitDate: Wed Sep 29 14:50:14 2021 +0200
more: POSIX compliance patch preventing exit on EOF without -e
で-eオプションが導入されて、デフォルトの挙動が変わっていました。とても煩わしいです。
さらにその後のコミットをたどっていくと、なんと、
commit 28b391ce7e58f8327c092b3911c05f526d0ad586
AuthorDate: Wed Jun 15 10:03:44 2022 +0200
CommitDate: Wed Jun 15 10:03:44 2022 +0200
more: restore exit-on-eof if POSIXLY_CORRECT is not set
In version 2.38, exit-on-eof has been disabled by default. This change
is annoying for users and forces many users to use 'alias more="more
-e"'. It seems better to force POSIX lovers to use POSIXLY_CORRECT
env. variable and stay backwardly compatible by default.
Addresses: https://github.com/util-linux/util-linux/issues/1703
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2088493
がコミットされていて、POSIXでないとやだ!っていう人は環境変数POSIXLY_CORRECTを使いなさいという形に戻っていました。
Debian 12のパッケージ更新タイミングの運のなさよ。とりあえず、alias more="more -e"で回避するしか無さそうです。
