title: Why does numpy.dot behave in this way?
body: <p>I'm trying to understand why numpy's <code>dot</code> function behaves as it does:</p>
  
  <pre><code>M = np.ones((9, 9))
  V1 = np.ones((9,))
  V2 = np.ones((9, 5))
  V3 = np.ones((2, 9, 5))
  V4 = np.ones((3, 2, 9, 5))
  </code></pre>
  
  <p>Now <code>np.dot(M, V1)</code> and <code>np.dot(M, V2)</code> behave as
  expected. But for <code>V3</code> and <code>V4</code> the result surprises
  me:</p>
  
  <pre><code>&gt;&gt;&gt; np.dot(M, V3).shape
  (9, 2, 5)
  &gt;&gt;&gt; np.dot(M, V4).shape
  (9, 3, 2, 5)
  </code></pre>
  
  <p>I expected <code>(2, 9, 5)</code> and <code>(3, 2, 9, 5)</code> respectively. On the other hand, <code>np.matmul</code>
  does what I expect: the matrix multiply is broadcast
  over the first <em>N - 2</em> dimensions of the second argument and
  the result has the same shape:</p>
  
  <pre><code>&gt;&gt;&gt; np.matmul(M, V3).shape
  (2, 9, 5)
  &gt;&gt;&gt; np.matmul(M, V4).shape
  (3, 2, 9, 5)
  </code></pre>
  
  <p>So my question is this: what is the rationale for
  <code>np.dot</code> behaving as it does? Does it serve some particular purpose,
  or is it the result of applying some general rule?</p>