【发布时间】:2018-10-08 12:33:17
【问题描述】:
我编写了一个在 MATLAB 中训练一维 Kohonen 网络的脚本,它的作用就像一个魅力。然后我尝试将它翻译成 Python 2.7,这是一种我很新的语言,而且脚本需要很长时间才能运行。
我会解释我正在做什么,看看这里是否有人可以对此事有所了解。我在矩阵y 中有一个给定的数据集,我想用它训练不同的 SOM。 SOM 是一维的(一条线),其神经元数量各不相同。我首先训练了一个大小为 N=2 的 SOM,最后训练了 N=NMax,总共得到了 NMax-2+1 SOM。对于每个 SOM,我想在训练结束后存储权重,然后再转到下一个 SOM。
在 MATLAB 中,NMax = 5 和 iterMax = 50 需要 9.74 秒。在 Python 中,54.04 秒。这种差异是巨大的,而实际的数据集、SOM 数量和迭代次数甚至更大,因此 Python 代码需要永远结束。
我当前的代码如下:
import numpy as np
import time
y = np.random.rand(2500,3) # Create random dataset to test
def A(d,s): # Neighborhood function
return np.exp(-d**2 / (2*s**2))
sigma_0 = float(5) # Initial standard deviation for A
eta_0 = float(1) # Initial learning rate
iterMax = 250 # Maximum number of iterations
NMax = 10 # Maximum number of neurons
w = range(NMax - 1) # Initialize the size of the weight matrix (it will store NMax-2+1 sets of weights, each of varying size depending on the value of N)
#%% KOHONEN 1D
t = time.time() # Start time
for N in np.arange(2,NMax + 1): # Size of the network
w[N - 2] = np.random.uniform(0,1,(N,np.size(y,axis=1))) - 0.5 # Initial weights
iterCount = 1; # Iteration counter
while iterCount < iterMax:
# Mix the datapoints to choose them in random order
mixInputs = y[np.random.permutation(np.size(y,axis = 0)),:]
# Decrease the value of the variance and the learning rate
sigma = sigma_0 - (sigma_0/(iterMax + 1)) * iterCount
eta = eta_0 - (eta_0/(iterMax + 1)) * iterCount
for kk in range(np.size(mixInputs,axis = 0)): # Picking one datapoint at a time
selectedInput = mixInputs[kk,:]
# These two lines calculate the weight that is the nearest to the datapoint selected
aux = np.absolute(np.array(np.kron(np.ones((N,1)),selectedInput)) - np.array(w[N - 2]))
aux = np.sum(np.abs(aux)**2,axis=-1)
ii = np.argmin(aux) # The node ii is the winner
for jj in range(N):
dist = min(np.absolute(ii-jj) , np.absolute(np.absolute(ii-jj)-N)) # Centering the neighborhood function in the winner
w[N - 2][jj,:] = w[N - 2][jj,:] + eta * A(dist,sigma) * (selectedInput - w[N - 2][jj,:]) # Updating the weights
print(N,iterCount)
iterCount = iterCount + 1
elapsedTime = time.time() - t
在 MATLAB 中,每次迭代(每次变量 iterCount 增加 1)几乎都是即时的。在 Python 中,每一个都需要很长时间。我不知道为什么它们的表现如此不同,但我想看看是否可以加快 Python 版本的速度。有什么建议吗?
编辑:根据 cmets 的要求,这里是更快的 MATLAB 版本的代码。
y = rand(2500,3) % Random dataset
A = @(d,s) exp(-d^2 / (2*s^2));
sigma_0 = 5;
eta_0 = 1;
iterMax = 250;
NMax = 10;
w = cell(NMax - 1,1);
%% KOHONEN 1D
tic();
for N = 2 : NMax
w{N - 1} = rand(N,size(y,2)) - 0.5;
iterCount = 1;
while (iterCount < iterMax)
mixInputs = y(randperm(size(y,1)),:);
sigma = sigma_0 - (sigma_0/(iterMax + 1)) * iterCount;
eta = eta_0 - (eta_0/(iterMax + 1)) * iterCount;
for kk = 1 : size(mixInputs,1)
input = mixInputs(kk,:);
% [~,ii] = min(pdist2(input,w{N - 1}));
aux = abs(repmat(input,N,1) - w{N - 1});
[~,ii] = min((sum(aux.^2,2)));
for jj = 1 : N
dist = min(abs(ii-jj) , abs(abs(ii-jj)-N));
w{N - 1}(jj,:) = w{N - 1}(jj,:) + eta * A(dist,sigma) * (input - w{N - 1}(jj,:));
end
end
N % Show N
iterCount = iterCount + 1 % Show iterCount
end
end
toc();
【问题讨论】:
-
你使用的是什么版本的东西?我在 Python 3.4.5 上,收到错误
Traceback (most recent call last): File "so.py", line 19, in <module> w[N - 2] = np.random.uniform(0,1,(N,np.size(y,axis=1))) - 0.5 # Initial weights -
@Prune 我忘了写下来,抱歉。我正在使用 Python 2.7。我已将该信息添加到问题中,谢谢!
-
您是否对它进行了检测/分析?我现在正在跑步,如果可以的话,我会在答案中提供分析。 docs.python.org/2/library/profile.html
-
@Attie 不,我没有(我什至不知道这些词的存在!)。我会检查那个链接,看看我可以在问题中添加什么,谢谢!
-
@Cleb 我已经添加了!
标签: python matlab optimization