【问题标题】:MNIST training time in CPUCPU 中的 MNIST 训练时间
【发布时间】:2019-09-29 09:46:17
【问题描述】:

我在Java 中创建了一个简单的前馈神经网络库 - 我需要一个基准来比较我的库并对其进行故障排除。

电脑规格:

  • AMD 锐龙 7 2700X 八核处理器
  • 内存 16.0 GB
  • WINDOWS 10 操作系统
  • JVM 参数:-Xms1024m -Xmx8192m

请注意,我没有使用 GPU。

请列出以下规格:

  • 电脑规格?
  • GPU 或 CPU(提供了 CPU,但 GPU 是很好的信息)
  • 输入数量 784(这是固定的)
  • 对于每一层:
    • 有多少个节点?
    • 什么激活函数?
  • 输出层:
    • 有多少个节点? (分类时为 10,回归时为 1)
    • 什么激活函数?
  • 什么损失函数?
  • 什么梯度下降算法(即:vanilla)
  • 批量大小是多少?
  • 多少个纪元? (不是迭代)
  • 最后,训练时间和准确率是多少?

非常感谢

编辑

只是为了说明我正在处理的内容。我用

创建了一个网络
  • 784 个输入节点
  • 784 在隐藏层 0
  • 隐藏层 1 中有 256 个
  • 隐藏层 2 中的 128 个
  • 1 个输出节点
  • 小批量大小 5
  • 16 个线程用于反向传播 它已经训练了大约 8 个小时,只完成了 694 次迭代——这甚至不到一个 epoch 的 20%。

我已经看到了一些声明,这如何在几分钟内完成?

【问题讨论】:

  • 我不清楚你想要什么。您是否希望有人使用 MNIST 数据集训练网络并报告性能?
  • @rayryeng 我假设有人已经有了 - 他们有可用的信息
  • 可能不是 - MNIST 是一个玩具数据集,通常仅用于演示目的,以表明神经网络可以在几个时期内实现更高的准确性和性能。无论您使用任何包或框架,结果都是相当可重现的。很可能有人必须设置它并再次运行它才能给你想要的东西——我不相信很多人会想要这样做。
  • @rayryeng 然后我会添加赏金 - 或者 Venmo 某人:)
  • @EdvBeq,您可能需要考虑在 AWS、GCP、Azure 等中启动不同规格的虚拟机并自己构建所需的列表:)

标签: python tensorflow neural-network mnist


【解决方案1】:

784 个输入节点 784 在隐藏层 0 隐藏层 1 中的 256 隐藏层 2 中的 128 1个输出节点 小批量大小 5

您可以做得更薄:784 => 784/2、160、40,批量大小至少为 50。

是的,java 中的事件,通常很慢,天真的解决方案必须像 几分钟 为 COMPLETE 那样运行,火车意味着 10~20 个 epoch。

你是如何实现它的?不要告诉你有一个神经元类,每个神经元都由一个实例表示。

它不应该运行如此可怕的慢。我知道的优化是表示点转置的第二个矩阵并使用 strassen-vinograd 算法,但你做错了其他事情

看看我的点实现:

import java.util.Arrays;

public class JTensor {


private float [] data;// contains data.length

private int width;



public static void dot_T(double [] out, double [] x, double [] y, int wy) {

    int iOut = 0;
    for (int ix = 0; ix < x.length; ix+=wy) {

        for (int iy = 0; iy < y.length;) {

            int ixv = ix;

            int iyLimit = iy + wy;
            double summ = 0;
            for(;iy <iyLimit;) {                    
                summ += x[ixv++] * y[iy++];             

            }
            out[iOut++] = summ;         



        }


    }


}

public static void main(String[] args) {

    System.out.println("generate random");

    int size = 1000;

    double []x = new double [size * size];

    double []y = new double [size * size];

    double []out = new double [size * size];

     for (int i = 0; i < x.length; i++) {            
         x[i] = (double)i   ;       
    }

     for (int i = 0; i < y.length; i++) {            
         y[i] = (double)i   ;           
    }       

    System.out.println("start ");
    long start = System.nanoTime();

    JTensor.dot_T(out, x,y,size);

    long end = System.nanoTime();

    System.out.println("elapsed " + ((end- start)/ (1000.0*1000*1000)));

    //System.out.println(Arrays.toString( x));
    //System.out.println(Arrays.toString( y));
    //System.out.println(Arrays.toString( out));


}

【讨论】:

  • “不要告诉你有一个神经元类,每个神经元都由一个实例表示。”哈哈是的 - 实际上我为每个节点和从一个节点到另一个节点的每个连接都有一个类实例。这很糟糕吗?
  • 天啊...是的。您应该只使用矩阵运算 - 点积和 elementvise 运算符来执行此操作。同样在java中将矩阵表示为一维数组,第二个矩阵由于顺序访问而被转置,并且也像一维数组,看看自己如何对它们进行mult。
  • 这也说明了 java 对象与原始操作相比如何慢
  • 是的,我现在可以看到这一点——但这是我可以将我的思想围绕它的唯一方法。我迷失在矩阵运算中
  • 好的,等一下,我会找到我的点产品实现。很久以前我也用java写过NN来好玩
【解决方案2】:

不太清楚您正在寻找的基准,它是从训练角度来看的性能还是准确性?为了准确起见,有一些工具可以在预测和实际之间进行比较,以便您衡量性能

【讨论】: