使用KernelML的自动编码器和并行计算

zombee0 2018-06-16

使用KernelML的自动编码器和并行计算

KernelML有许多潜在的用例,但它并不总是最好的工具。这个实验的目标是找到潜在的用例,在这些用例中,kernelml比现有的软件包(如Keras或PyTorch)提供了一些优势,用于构建神经网络。一种似乎具有潜力的用例是自动编码。自编码器可用于从数据构造潜在变量。我们可以将潜在层定义为非线性系统,并使输出的偏导数相对于输入参数非常数。有那些可以解决无梯度黑盒系统的软件包,例如scikit-optimize,但从我所知道的大多数情况来看,并不关注机器学习。为了测试KernelML,我们将使用autoencoder来处理 higgs boson(https://www.kaggle.com/c/higgs-boson/)训练数据集的特征,同时强制一个非线性潜变量结构并将一些参数限制为正值。通过使用'黑魔法'的方法,KernelML可以用来一次生成不同的潜在特征。这些功能可以包含在预测模型中以增强预测。

Keras能够使用线性激活层有效地模拟训练和验证输入数据集中99%的变化。它还创建了一个编码器模型来生成潜在变量。

那么使用KernelML有什么意义呢?

1、每个层的参数可以是非线性的。

2、每个参数都可以从不同的随机分布中抽样

3、可以将参数转换为满足某些约束条件。

4、网络组合是用numpy操作来定义的。

5、参数概率更新

6、每个参数更新在本地或全局最小值附近的损失函数。

KerneML规格

KernelML是可以用来训练机器学习算法的蛮力优化器。该软件包使用机器学习和蒙特卡罗模拟来优化一个具有用户定义的损失函数的参数向量。使用kernelml为大型复杂网络创建了很高的计算成本,因为它用一个子空间对参数向量中每个参数的损失函数进行了抽样,这需要许多随机模拟。通过启用与ipyparallel的并行计算,降低了计算成本。之所以决定使用这个包,是因为它有效地利用了机器上的核心。

令人尴尬的并行计算

Ipython并行是一个很好的并行计算包!我选择了这个包,因为它允许您在执行计算之前将静态数据推送到客户端的内核。这与python的内置多处理包相反,文档建议不要在进程之间共享数据。假设我们有1千兆字节的数据要在4个内核上处理。如果我们需要在每次迭代时在4个内核中推送1千兆字节,它会使程序减慢很多。只要我们不需要推送大量数据,多处理库仍然有用。例如,通过多处理可以高效地完成多个分布的随机数据生成,因为我们只需要推送分布的参数。确保所有软件包都已安装并更新

pip install --upgrade ipython

pip install --upgrade setuptools pip

pip install ipython [all]

要在OS X上启动并行计算群集,只需打开一个新的终端窗口并键入以下内容:

ipcluster start -n 4 //此机器上有4个内核

然后我们需要一些代码来初始化并行引擎。首先,我们导入默认配置文件。此配置文件包含有关如何初始化机器上的核心的信息,并应自动创建。然后,将所有并行内核(dview)的'block参数'设置为true。这确保所有内核的结果都是同步返回的。

from ipyparallel import Client

rc = Client(profile='default')

dview = rc[:]

dview.block = True

with dview.sync_imports():

#for some reason, aliases cannot be use

import numpy

import scipy

kml = kernelml.KernelML()

kml.use_ipyparallel(dview)

神经网络和KernelML

Kernelml优化了一个参数vector,给定一个损失函数,所以需要将参数vector转换成一个张量(在本例中是一个矩阵的列表)。在下面的Python代码块中,定义了一个示例helper类来转换矩阵列表中的参数vector。类接受三个输入:1)the layer shapes 2)输入的数量3)输出的数量。例如,如果输入数= 30,输出数= 1,层形为[10,30],则相应的模型形状和参数形状分别为[30,30,1],[300,300,30]。

from scipy import stats

class NNShapeHelper():

def __init__(self,layer_shape,num_inputs,num_outputs):

self.N_inputs = num_inputs

self.N_outputs = num_outputs

self.layer_shape = layer_shape

self.N_layers = len(layer_shape)

self.model_shape = []

self.parameter_shape = []

def get_N_parameters(self):

self.model_shape.append(self.N_inputs)

input_n_parameters = self.N_inputs*self.layer_shape[0]

N = input_n_parameters

self.parameter_shape.append(input_n_parameters)

for i in range(1,self.N_layers):

layer_n_parameters = self.layer_shape[i-1]*self.layer_shape[i]

self.model_shape.append(self.layer_shape[i])

self.parameter_shape.append(layer_n_parameters)

N += layer_n_parameters

output_n_parameters = self.N_outputs*self.layer_shape[-1]

N += output_n_parameters

self.model_shape.append(self.N_outputs)

self.parameter_shape.append(output_n_parameters)

self.N_parameters = N

return N

这个结果可以用在一个重塑函数中,如下面的例子所示。该函数将参数作为输入并返回包含每个层参数的张量。任何剩余的参数将返回到名为extra_w的参数向量中。模型和参数形状显式显示在函数中,但这些值作为完整代码中的参数传递给KernelML。

def reshape_vector(w):

reshape_w = []

indx = 0

for shape,num in zip([30, 30, 1], [300, 300, 30]):

x = w[indx:num+indx]

if x.size!=num:

continue

x = x.reshape(shape,int(num/shape))

reshape_w.append(x)

indx = indx+num

extra_w = w[indx:]

return reshape_w,extra_w

AutoEncoder

自编码器是一种模拟输入数据表示的神经网络。假设有一个数据集X,我们希望找到它的表示。autoencoder将使用X作为输入和输出,但会限制中间层具有比数据维度更少的“自由度”。例如,如果X具有32个维度,则中间的神经元数量将小于32.具有非线性激活层的自动编码器如下所示。为了好玩,我做了第一层与爱因斯坦场方程相同的形式。

使用KernelML的自动编码器和并行计算

该自动编码器由两个中间层组成,其中w1和w0是filters。@符号表示上述公式中的点积。在应用每个过filter后,将额外的参数应用于模型。注意:第二层输出的偏导数与输入参数相关,包括额外的参数,即alpha1,beta1。第一层中的非线性参数导致偏导数依赖于同一层中的其他参数。'layer recursive dependency'对KernelML不会造成任何问题。该模型将使模型输出与输入数据之间的均方误差最小化。

def autoencoder_function(X,y,w_tensor,args,predict=False):

#can't be passed to parallel engines, so I just assign the aliases manually

#this is an improvement from loading the libraries again

np = numpy

stats = scipy.stats

#arguement

model_shape,parameter_shape,link = args

# define the loss function between predicted output actual output

def nn_autoencoder_loss(hypothesis,y):

return np.sum((hypothesis-y)**2)/y.size

#reshape parameter vector into list of matrices

def reshape_vector(w):

reshape_w = []

indx = 0

for shape,num in zip(model_shape,parameter_shape):

x = w[indx:num+indx]

if x.size!=num:

continue

x = x.reshape(shape,int(num/shape))

reshape_w.append(x)

indx = indx+num

extra_w = w[indx:]

return reshape_w,extra_w

#Specifies the way the tensors are combined with the inputs

def combine_tensors(X,w_tensor,link):

w_tensor,extra_w = reshape_vector(w_tensor)

b1,a1,b2,a2 = extra_w[:4]

pred = X.dot(w_tensor[0])

#choose link on encoding layer

if link == 'linear':

pred = a1*(pred+b1)

elif link == 'field_eq':

pred = -0.5*a1*pred + b1*pred

elif link == 'log':

pred = a1*pred + np.log(np.abs(pred)+b1)

elif link == 'inverse':

pred = a1/(pred+b1)

pred = pred.dot(w_tensor[1].T)

pred = a2*(pred+b2)

return pred

#we cannot modify pickled memory so create a copy of the parameter vector

w_tensor_copy = w_tensor.copy()

pred = combine_tensors(X,w_tensor_copy,link)

if predict==True:

return pred

loss = nn_autoencoder_loss(pred,y)

return loss

KernelML被用来对higgs boson数据集中的特征进行自动编码。为了评估算法的性能,训练数据集被随机分成一个训练和验证数据集,每个数据集都有50%的原始数据,按比例采样。该数据集有30个未转换的特征和2,500,000个观察值。编码器层将有10个滤波器,而解码器层将有30个滤波器。NNShapeHelper类用于获取'reshape_vector'函数的模型和参数形状列表。使用KernelML进行优化的autoencoder损失函数在20次运行,100次迭代和〜2.0分钟后能够验证验证数据集中90%-95%的变化。另外,额外参数a1,b1,a2和b2被限制为正数。在拟合模型之后,使用编码器功能创建5个潜在变量,从最近10次运行中抽样。使用PCA将潜变量组合成3个特征,并将这些变量连接到特征数据集。最后,建立一个具有1个密集层和200个神经元的全连接神经网络来对目标变量进行分类。验证数据集中大约81%-82%的目标变量用潜变量正确分类。相比之下,没有潜在变量的情况下,精度为79%-80%。

黑魔法方法

这里是我用KernelML训练一个'大'网络的策略:

  • 1)找到相当数量的参数来分析
  • 2)使更新幅度相对较小
  • 3)在随机的数据部分训练模型
  • 4)重新运行优化器上次运行的最佳参数作为当前运行的先验
  • 5)将每次运行的迭代次数设置为较低的数字。
  • 6)使用随机小批量策略减少参数的数量以调整每次迭代。

使用KernelML的自动编码器和并行计算

KernelML操作顺序

KernelML优化参数:

1)sequential_update(是否按顺序更新参数)

2)update_magnitude(添加到参数更新的偏差)

3)analyze_n_parameters(方差添加到推理引擎)

4)n_parameter_updates(每次迭代执行多少更新)

5)percent_of_params_updated(更新参数的百分比)

6)zscore(收敛参数)

7)total_iterations(迭代次数)

使用KernelML的自动编码器和并行计算

这种方法需要调整随机样本的数量和需要分析的参数的数量。上面的图显示了对不同的analyze_n_parameters值的每个参数更新的损失,以及每个迭代的固定数量的随机模拟(6000)。为这个参数选择的值为1000、500和100,如图从左到右所示。中间的图,500,比其他两个图更平滑。我发现当损失曲线更平滑时算法的性能更好。总的来说,这个参数,analyze_n_parameters,应该至少等于系统中参数的数量。在kernelml之上创建一个优化平滑度的算法可能是一种兴趣。这些图可以通过指定plot_feedback=True从优化函数生成。

相关推荐