根据给定的示例有效地为大型数据集分配标签
Assign labels based on given examples for a large dataset effectively
我有矩阵 X (100000 X 10) 和向量 Y (100000 X 1)。 X 行是分类的并假定值为 1 到 5,标签也是分类的(11 到 20);
X 的行是重复的,只有 ~25% 的唯一行,我希望 Y 具有特定唯一行的所有标签的统计模式。
然后是另一个数据集 P (90000 X 10),我想根据之前的练习预测标签 Q。
我尝试的是在 MATLAB 中使用 unique 找到 X 的唯一行,然后为唯一行分配每个标签的统计模式。对于 P,我可以使用 ismember 并执行相同的操作。
问题出在数据集的大小上,完成该过程需要 1.5-2 小时。 MATLAB 中是否有矢量化版本?
这是我的代码:
[X_unique,~,ic] = unique(X,'rows','stable');
labels=zeros(length(X_unique),1);
for i=1:length(X_unique)
labels(i)=mode(Y(ic==i));
end
Q=zeros(length(P),1);
for j=1:length(X_unique)
Q(all(repmat(X_unique(j,:),length(P),1)==P,2))=label(j);
end
如果您将第一个循环完全替换为:
,您将能够大大加快您的第一个循环
labels = accumarray(ic, Y, [], @(y) mode(y));
第二个循环可以通过在 Q(...)
中使用 all(bsxfun(@eq, X_unique(i,:), P), 2)
来加速。假设您的数组不是很大 w.r.t,这是一种很好的矢量化方法。机器上的可用内存。此外,为了节省更多时间,您可以使用在 P
上对 X
所做的 unique
技巧,运行 在一个更小的数组上进行所有比较:
[P_unique, ~, IC_P] = unique(P, 'rows', 'stable');
编辑:
按以下方式计算 Q_unique
: 然后使用以下方法将其转换回完整数组:
Q_unique = zeros(length(P_unique),1);
for i = 1:length(X_unique)
Q_unique(all(bsxfun(@eq, X_unique(i,:), P_unique), 2)) = labels(i)
end
并转换回 Q_full
以匹配原始 P
输入:
Q_full = Q_unique(IC_P);
编辑结束
最后,如果内存是个问题,除了上述所有内容之外,您可能希望在第二个循环中使用半向量化方法:
for i = 1:length(X_unique)
idx = true(length(P), 1);
for j = 1:size(X_unique,2)
idx = idx & (X_unique(i,j) == P(:,j));
end
Q(idx) = labels(i);
% Q(all(bsxfun(@eq, X_unique(i,:), P), 2)) = labels(i);
end
与 bsxfun
相比,这将花费大约 x3
的时间,但如果内存有限,那么您必须以速度为代价。
另一个编辑
根据您的 Matlab 版本,您还可以通过将数字序列的文本表示映射到计算的 labels
来利用 containers.Map
。请参见下面的示例。
% find unique members of X to work with a smaller array
[X_unique, ~, IC_X] = unique(X, 'rows', 'stable');
% compute labels
labels = accumarray(IC_X, Y, [], @(y) mode(y));
% convert X to cellstr -- textual representation of the number sequence
X_cellstr = cellstr(char(X_unique+48)); % 48 is ASCII for 0
% map each X to its label
X_map = containers.Map(X_cellstr, labels);
% find unique members of P to work with a smaller array
[P_unique, ~, IC_P] = unique(P, 'rows', 'stable');
% convert P to cellstr -- textual representation of the number sequence
P_cellstr = cellstr(char(P_unique+48)); % 48 is ASCII for 0
% --- EDIT --- avoiding error on missing keys in X_map --------------------
% find which P's exist in map
isInMapP = X_map.isKey(P_cellstr);
% pre-allocate Q_unique to the size of P_unique (can be any value you want)
Q_unique = nan(size(P_cellstr)); % NaN is safe to use since not a label
% find the labels for each P_unique that exists in X_map
Q_unique(isInMapP) = cell2mat(X_map.values(P_cellstr(isInMapP)));
% --- END EDIT ------------------------------------------------------------
% convert back to full Q array to match original P
Q_full = Q_unique(IC_P);
在我的笔记本电脑上 运行 大约需要 15 秒。其中大部分用于计算 mode
.
我有矩阵 X (100000 X 10) 和向量 Y (100000 X 1)。 X 行是分类的并假定值为 1 到 5,标签也是分类的(11 到 20);
X 的行是重复的,只有 ~25% 的唯一行,我希望 Y 具有特定唯一行的所有标签的统计模式。
然后是另一个数据集 P (90000 X 10),我想根据之前的练习预测标签 Q。
我尝试的是在 MATLAB 中使用 unique 找到 X 的唯一行,然后为唯一行分配每个标签的统计模式。对于 P,我可以使用 ismember 并执行相同的操作。
问题出在数据集的大小上,完成该过程需要 1.5-2 小时。 MATLAB 中是否有矢量化版本?
这是我的代码:
[X_unique,~,ic] = unique(X,'rows','stable');
labels=zeros(length(X_unique),1);
for i=1:length(X_unique)
labels(i)=mode(Y(ic==i));
end
Q=zeros(length(P),1);
for j=1:length(X_unique)
Q(all(repmat(X_unique(j,:),length(P),1)==P,2))=label(j);
end
如果您将第一个循环完全替换为:
,您将能够大大加快您的第一个循环labels = accumarray(ic, Y, [], @(y) mode(y));
第二个循环可以通过在 Q(...)
中使用 all(bsxfun(@eq, X_unique(i,:), P), 2)
来加速。假设您的数组不是很大 w.r.t,这是一种很好的矢量化方法。机器上的可用内存。此外,为了节省更多时间,您可以使用在 P
上对 X
所做的 unique
技巧,运行 在一个更小的数组上进行所有比较:
[P_unique, ~, IC_P] = unique(P, 'rows', 'stable');
编辑:
按以下方式计算 Q_unique
: 然后使用以下方法将其转换回完整数组:
Q_unique = zeros(length(P_unique),1);
for i = 1:length(X_unique)
Q_unique(all(bsxfun(@eq, X_unique(i,:), P_unique), 2)) = labels(i)
end
并转换回 Q_full
以匹配原始 P
输入:
Q_full = Q_unique(IC_P);
编辑结束
最后,如果内存是个问题,除了上述所有内容之外,您可能希望在第二个循环中使用半向量化方法:
for i = 1:length(X_unique)
idx = true(length(P), 1);
for j = 1:size(X_unique,2)
idx = idx & (X_unique(i,j) == P(:,j));
end
Q(idx) = labels(i);
% Q(all(bsxfun(@eq, X_unique(i,:), P), 2)) = labels(i);
end
与 bsxfun
相比,这将花费大约 x3
的时间,但如果内存有限,那么您必须以速度为代价。
另一个编辑
根据您的 Matlab 版本,您还可以通过将数字序列的文本表示映射到计算的 labels
来利用 containers.Map
。请参见下面的示例。
% find unique members of X to work with a smaller array
[X_unique, ~, IC_X] = unique(X, 'rows', 'stable');
% compute labels
labels = accumarray(IC_X, Y, [], @(y) mode(y));
% convert X to cellstr -- textual representation of the number sequence
X_cellstr = cellstr(char(X_unique+48)); % 48 is ASCII for 0
% map each X to its label
X_map = containers.Map(X_cellstr, labels);
% find unique members of P to work with a smaller array
[P_unique, ~, IC_P] = unique(P, 'rows', 'stable');
% convert P to cellstr -- textual representation of the number sequence
P_cellstr = cellstr(char(P_unique+48)); % 48 is ASCII for 0
% --- EDIT --- avoiding error on missing keys in X_map --------------------
% find which P's exist in map
isInMapP = X_map.isKey(P_cellstr);
% pre-allocate Q_unique to the size of P_unique (can be any value you want)
Q_unique = nan(size(P_cellstr)); % NaN is safe to use since not a label
% find the labels for each P_unique that exists in X_map
Q_unique(isInMapP) = cell2mat(X_map.values(P_cellstr(isInMapP)));
% --- END EDIT ------------------------------------------------------------
% convert back to full Q array to match original P
Q_full = Q_unique(IC_P);
在我的笔记本电脑上 运行 大约需要 15 秒。其中大部分用于计算 mode
.