title: How to avoid Kronecker product in NumPy computations
body: <h2><strong>Background</strong></h2>
  
  <p>After generating a list of random weights:</p>
  
  <pre><code>sizes = [784,30,10]
  weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1],sizes[1:])]
  </code></pre>
  
  <p>utilize Numpy's Kronecker product to create <code>foo</code> (with shape <code>(900, 23520)</code>): </p>
  
  <pre><code>foo = np.kron(np.identity(30),weights[0])
  </code></pre>
  
  <p>Then, matrix multiply <code>foo</code> with a slice from <code>data</code>, namely,</p>
  
  <pre><code>bar = np.dot(foo,data[0])
  </code></pre>
  
  <p>whereby the <code>data[0].shape</code> is <code>(23520,)</code> and <code>data[0].dtype</code> is <code>float32</code>.</p>
  
  <h2><strong>Question</strong></h2>
  
  <p><code>foo</code> is rather wasteful. How can <code>weights[0]</code>, which has shape <code>(30,784)</code>, be utilized for the multiplication with <code>data[0]</code> in a more resourceful manner?</p>
  
  <p>More generally, <code>data[0]</code> is a slice from an array with shape <code>(1666,23520)</code>, so the multiplication procedure will need to be carried out 1666 times. Also, the data array is close to sparse with less than 20% of entries being non-zero.</p>
  
  <p>Here's the loop I had tried:</p>
  
  <pre><code>for i in range(len(data)):
      foo = np.kron(np.identity(30),weights[0])
      bar = np.dot(foo,data[i])
  </code></pre>