nuget server logo nuget api documents
↑

API Docs / Microsoft.VisualBasic.MachineLearning.t-SNE / Helper

Helper

Full name Microsoft.VisualBasic.MachineLearning.tSNE.Helper Assembly Microsoft.VisualBasic.MachineLearning.t-SNE Members 17

01 Syntax

Microsoft.VisualBasic.MachineLearning.tSNE.Helper

02 Methods

NameOverloadsSummary
ParallelOptions 1 依据给定的并行度创建一个 ParallelOptions 对象
TaskBlockSize 1 计算任务分块的大小
TaskBlockCount 1 依据分块大小计算任务块的数量
SumParts 1 串行合并各个任务块的局部累加值
SumColumnParts 1 串行合并各个任务块的局部向量累加值
zeros 1 utilitity that creates contiguous vector of zeros of size n
L2 1 compute L2 distance between two vectors
xtod 1 并行计算两两距离矩阵
ReleaseWorkspace 1 线程私有缓冲区的释放回调(Parallel.For 的 localFinally 需要一个非空委托)
QuickSelect 1 在 arr 的前 n 个元素中找出第 k 大的值
d2pSparse 1 每行仅保留 top-k 近邻,构建稀疏的联合概率矩阵
ProcessRow 1 处理第 i 行:现算(或读取)距离 → beta 二分搜索 → top-k 选择 → 双向展开写入
EmitPair 1 把 (i, j, v) 双向写入键/值数组,同时完成 (p_{j|i} + p_{i|j}) 的对称化展开
d2p 1 compute (p_{i|j} + p_{j|i})/(2n)
ReleaseRowBuffer 1 线程私有缓冲区的释放回调
SearchPrecision 1 对第 i 行执行 beta 二分搜索,把最终的条件概率写入 P 的第 i 行
Symmetrize 1 symmetrize P and normalize it to sum to 1 over all ij

03 Members

method ParallelOptions #
ParallelOptions(Int32)

依据给定的并行度创建一个 ParallelOptions 对象

Parameters
NameTypeDescription
nthreadsInt32

并行线程数,小于等于 0 时表示不限制(交由 TPL 的线程池自行调度)

method TaskBlockSize #
TaskBlockSize(Int32, Int32, Int32)

计算任务分块的大小

Remarks

归约(qsum / cost / Z / ymean)采用「连续分块 + 每块一个局部累加器 + 按块序串行合并」 的方式,而不是 Parallel.For(Of TLocal) + Interlocked: 省掉了每个元素一次的委托调用与原子操作开销。

分块方案刻意只取决于任务总量而与线程数无关,这带来两个好处: 一是浮点累加的分组方式是固定的,因此同一个数据集在同一台机器上 无论把 nthreads 设成多少,结果都逐位一致(可复现性); 二是任务块数量远多于线程数,TPL 的动态调度可以自动填平 三角循环(第 i 行的工作量随 i 增大而减小)带来的负载不均。

命名为 TaskBlockSize 而不是 BlockSize,是为了避免与调用方常见的 局部变量名 blockSize 相冲突(VB 是大小写不敏感的)。

Parameters
NameTypeDescription
totalInt32

任务总量

maxBlocksInt32

任务块数量的上界

minItemsInt32

单个任务块的元素数量下界,用于避免把任务切得过碎导致调度开销反超收益

method TaskBlockCount #
TaskBlockCount(Int32, Int32)

依据分块大小计算任务块的数量

Parameters
NameTypeDescription
totalInt32

-

blockSizeInt32

-

method SumParts #
SumParts(Double())

串行合并各个任务块的局部累加值

method SumColumnParts #
SumColumnParts(Double()(), Int32)

串行合并各个任务块的局部向量累加值

Remarks

放在独立的函数里而不是就地展开,是为了避免 VB 大小写不敏感导致的 循环变量与外层局部变量(例如 d 与 D)重名的编译错误。

Parameters
NameTypeDescription
partsDouble()()

-

[dim]Int32

-

method zeros #
zeros(Int32)

utilitity that creates contiguous vector of zeros of size n

Parameters
NameTypeDescription
nInt32

-

method L2 #
L2(Double(), Double())

compute L2 distance between two vectors

Parameters
NameTypeDescription
x1Double()

-

x2Double()

-

method xtod #
xtod(Double()(), Int32)

并行计算两两距离矩阵

Remarks

按外层行 i 分派。第 i 个任务只写第 i 行与第 i 列(三角对称), 不同的 i 之间所写入的单元格集合互不相交,因此无需加锁。

Parameters
NameTypeDescription
XDouble()()

-

nthreadsInt32

并行线程数,<=0 表示不限制

method ReleaseWorkspace #
ReleaseWorkspace(RowWorkspace)

线程私有缓冲区的释放回调(Parallel.For 的 localFinally 需要一个非空委托)

method QuickSelect #
QuickSelect(Double(), Int32, Int32)

在 arr 的前 n 个元素中找出第 k 大的值

Remarks

3-way 快排选择,平均 O(n),用于避免对每一行做 O(n log n) 的全排序

Parameters
NameTypeDescription
arrDouble()

会被就地分区打乱,调用前请自行备份

nInt32

-

kInt32

0-based,0 表示最大值

method d2pSparse #
d2pSparse(Double, Double, Int32, Int32, Double()(), Double())

每行仅保留 top-k 近邻,构建稀疏的联合概率矩阵

Remarks

这个函数全程不物化 N×N 的稠密概率矩阵,是 Barnes-Hut 模式得以突破 O(N²) 内存墙的关键。

走 X 分支时,连 N×N 的距离矩阵都不需要物化 (每一行在用到时才现算,用完即弃,内存占用仅 threads × N); 走 D 分支时距离矩阵由调用方提供,但概率矩阵依然是稀疏的。

对称化采用「双向展开」而非字典合并:对于每一行的第 m 个近邻 j, 分别写入 (i, j, p{j|i}) 与 (j, i, p{j|i})。 于是对于无序对 {i, j},行 i 上会同时收到 p{j|i}(来自行 i 自身的近邻表)与 p{i|j}(来自行 j 的近邻表所展开出的反向条目),两者相加恰好等于 联合概率定义中的 (p{j|i} + p{i|j}),因此无需再做一次 O(nnz) 的合并去重。

Parameters
NameTypeDescription
perplexityDouble

困惑度

tolDouble

beta 二分搜索的收敛容差

kInt32

每一行保留的近邻数量

nthreadsInt32

并行线程数

XDouble()()

高维原始数据;与 D 二者必须恰好提供一个

DDouble()

预先计算好的 N×N 距离矩阵;与 X 二者必须恰好提供一个

method ProcessRow #
ProcessRow(Double()(), Double(), Int32, Int32, Double, Double, Int32, RowWorkspace, Int64(), Double())

处理第 i 行:现算(或读取)距离 → beta 二分搜索 → top-k 选择 → 双向展开写入

method EmitPair #
EmitPair(Int64(), Double(), Int32, Int32, Int32, Int32, Double)

把 (i, j, v) 双向写入键/值数组,同时完成 (p{j|i} + p{i|j}) 的对称化展开

method d2p #
d2p(Double(), Double, Double, Int32)

compute (p{i|j} + p{j|i})/(2n)

Parameters
NameTypeDescription
DDouble()

distance matrix

perplexityDouble

-

tolDouble

-

method ReleaseRowBuffer #
ReleaseRowBuffer(Double())

线程私有缓冲区的释放回调

method SearchPrecision #
SearchPrecision(Double(), Double(), Int32, Int32, Double, Double, Double())

对第 i 行执行 beta 二分搜索,把最终的条件概率写入 P 的第 i 行

method Symmetrize #
Symmetrize(Double(), Int32, Int32)

symmetrize P and normalize it to sum to 1 over all ij

Remarks

第 i 个任务只写输出矩阵的第 i 行,行与行之间互不相交,可安全并行。

Parameters
NameTypeDescription
PDouble()

稠密的条件概率矩阵,行主序

NInt32

-

nthreadsInt32

并行线程数

Returns

对称化之后的联合概率矩阵