【问题标题】:Multithreading for backpropagation algorithm反向传播算法的多线程
【发布时间】:2014-08-04 03:02:02
【问题描述】:

为了加快一些神经网络的学习速度,我尝试了一些多线程,因为对于特定的层,每个神经元的计算是相互独立的。

我使用的原始函数是一些基本的反向传播算法,用于评估网络中的增量:

δ = 导数 * Σ(权重 * 前一个 δ)

void backpropagation (Autoencoder* AE)
{
   int i, j, k;
   for(i = AE->numLayer-2; i >= 0; i--)
   {
      for(j = 0; j < AE->layer[i].size; j++)
      {
         register double sum = 0.0;
         for(k = 0; k < AE->layer[i+1].size; k++)
         {
            sum += AE->layer[i+1].neuron[k].weight[j] * AE->layer[i+1].neuron[k].delta;
         }
         AE->layer[i].neuron[j].delta = AE->layer[i].neuron[j].derivative * sum;
      }
   }
}

自动编码器是包含神经网络的结构。它工作得很好,虽然有点慢,而且首先尝试这个功能似乎是个好主意。

修改后的功能如下:

void backpropagationmultithread (Autoencoder* AE, unsigned int ncore, pthread_t* pth)
{
   int i, j;
   unsigned int neuronpercore, extra;
   sem_t semaphore;
   argThread* args[ncore];
   for(i = AE->numLayer-2; i >= 0; i--)
   {
      neuronpercore = AE->layer[i].size / ncore;
      extra = neuronpercore + (AE->layer[i].size % ncore);
      sem_init(&semaphore, 0, -ncore);
      for(j = 0; j < ncore; j++)
      {
         args[j] = malloc(sizeof(argThread));
         args[j]->layer = i;
         args[j]->AE = AE;
         args[j]->sem = &semaphore;
         args[j]->startat = neuronpercore * j;
         args[j]->nneurons = (j!=ncore-1)?neuronpercore:extra;
         pthread_create(&pth[j], NULL, backpropagationthread, (void*)args[j]);
      }
      sem_wait(&semaphore);
      for(j = 0; j < ncore; j++)
      {
         pthread_cancel(pth[j]);
      }
   }
}

以及新线程的功能:

void* backpropagationthread (void* arg)
{
   argThread* args = (argThread*) arg;
   unsigned int j,k,layer = args->layer, start = args->startat, end = args->startat + args->nneurons;
   Autoencoder* AE = args->AE;
   for(j = start; j < end; j++)
   {
      register double sum = 0.0;
      for(k = 0; k < AE->layer[layer+1].size; k++)
      {
         sum += AE->layer[layer+1].neuron[k].weight[j] * AE->layer[layer+1].neuron[k].delta;
      }
      AE->layer[layer].neuron[j].delta = AE->layer[layer].neuron[j].derivative * sum;
   }
   sem_post(args->sem);
   free(arg);
   return NULL;
}

argThread 只是一个包含要传递给线程的所有参数的小结构,ncore 是 CPU 内核的数量。这个想法是将每一层分成大致相等数量的神经元,由每个线程单独处理(如果它们不是倍数,则最后一个具有所有额外的神经元)。

新函数在某种程度上确实可以工作,而且速度更快,但是在某个阈值之后不再收敛,而旧函数会收敛,我找不到它的行为会改变的原因。我是否遗漏了一些神经元或权重?

【问题讨论】:

  • 好吧,我承认我在 Windows 中待了多年,最近才重新回到 pthreads,但是为什么你要向你的线程句柄发送取消请求而不是 pthread_join()-ing 他们呢?
  • 我不太确定线程完成后如何处理它们。我尝试删除该部分,但实际上没有任何变化。

标签: c multithreading machine-learning neural-network backpropagation


【解决方案1】:

前段时间我为 Encog 实现了一个多线程反向传播算法。我用 Java 写了这个,但是当我用 C 实现它时,我使用了 OpenMP,而不是 pthreads。你可以在这里看到我的 C 实现。

https://github.com/encog/encog-c

我还写了一篇关于我在多线程中执行反向传播的方法的文章。 你可以在这里看到我的文章。

http://www.heatonresearch.com/encog/mprop/compare.html

在 Stack Overflow 上还有其他一些关于此的问题。大多数似乎都参考了我的算法。

Multithreaded backpropagation How can I apply multithreading to the backpropagation neural network training?

【讨论】:

    猜你喜欢
    • 2012-02-03
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 2021-12-10
    • 2014-01-10
    • 2013-11-28
    • 2017-05-12
    相关资源
    最近更新 更多