Advertisement
Guest User

Einsum Usage

a guest
Feb 5th, 2016
1,238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.28 KB | None | 0 0
  1. #  1: Imports.
  2. import numpy as np
  3.  
  4. #  2: Invocation. Requires format string + any # of input args.
  5. arg0 = np.random.normal(...)
  6. arg1 = np.random.normal(...)
  7. ...
  8. argn = np.random.normal(...)
  9.  
  10. # ...
  11.  
  12. dst  = np.einsum("               ", arg0, arg1, ..., argn)
  13.  
  14. #  3: Format string. Incomplete example with 3 input args.
  15. dst  = np.einsum("  ,   ,  ->    ", arg0, arg1, arg2)
  16.  
  17. #  4: Format string. Incomplete example with 3 input args.
  18. dst  = np.einsum("  ,   ,  ->    ", arg0, arg1, arg2)
  19.  
  20.  
  21.  
  22.  
  23. assert arg0.ndim == len("  ")                # (Order-2 Tensor)
  24. assert arg1.ndim == len("   ")               # (Order-3 Tensor)
  25. assert arg2.ndim == len("  ")                # (Order-2 Tensor)
  26. assert dst .ndim == len("    ")              # (Order-4 Tensor)
  27.  
  28. #  5: Format string. Complete examples with 1 and 2 args.
  29. s = np.einsum("a->",       v   )
  30. T = np.einsum("ij->ji",    M   )
  31. C = np.einsum("mn,np->mp", A, B)
  32.  
  33.  
  34. assert v.ndim == len("a")
  35. assert s.ndim == len("")
  36.  
  37. assert M.ndim == len("ij")
  38. assert T.ndim == len("ji")
  39.  
  40. assert A.ndim == len("mn")
  41. assert B.ndim == len("np")
  42. assert C.ndim == len("mp")
  43.  
  44. #  6: Elaborated Example. Matrix multiplication.
  45. #     C     =     A     *     B
  46. #  Ni x Nj  =  Ni x Nk  *  Nk x Nj
  47. #               |    ^-----^     |
  48. #               |     Match      |
  49. #               |                |
  50. #               -------- ---------
  51. #                       V
  52. #  Ni x Nj  <------- Ni x Nj
  53.  
  54. C = np.empty((Ni,Nj))
  55. for i in xrange(Ni):
  56.       for j in xrange(Nj):
  57.              total = 0
  58.              
  59.              for k in xrange(Nk):
  60.                    total += A[i,k]*B[k,j]
  61.              
  62.              C[i,j] = total
  63.  
  64.  
  65.  
  66.  
  67. C = np.einsum("ik,kj->ij", A, B)
  68.  
  69. #  7. Free Indices
  70. C = np.empty((Ni,Nj))
  71. for i in xrange(Ni):
  72.       for j in xrange(Nj):
  73.              total = 0
  74.              
  75.              for k in xrange(Nk):
  76.                    
  77.                    total += A[i,k]*B[k,j]
  78.              
  79.              C[i,j] = total
  80.  
  81.  
  82.  
  83.  
  84. C = np.einsum("ik,kj->ij", A, B)
  85.  
  86. #  8. Summation Indices
  87. C = np.empty((Ni,Nj))
  88. for i in xrange(Ni):
  89.       for j in xrange(Nj):
  90.              total = 0
  91.              
  92.              for k in xrange(Nk):
  93.                    
  94.                    total += A[i,k]*B[k,j]
  95.              
  96.              C[i,j] = total
  97.  
  98.  
  99.  
  100.  
  101. C = np.einsum("ik,kj->ij", A, B)
  102.  
  103. #  9. Elaborated Example. Matrix diagonal extraction.
  104. d = np.empty((Ni))
  105. for i in xrange(Ni):
  106.       total = 0
  107.      
  108.      
  109.       total +=       M[i,i]
  110.      
  111.       d[i] = total
  112.  
  113.  
  114.  
  115.  
  116. d = np.einsum("ii->i", M)
  117.  
  118. # 10. Elaborated Example. Matrix trace.
  119. Tr = 0   # Scalar! Has dimension 0 and no indexes
  120.  
  121.  
  122. total = 0
  123.  
  124. for i in xrange(Ni):
  125.       total +=       M[i,i]
  126.  
  127. Tr = total
  128.  
  129.  
  130.  
  131.  
  132. Tr = np.einsum("ii->", M)
  133.  
  134. # 11. Elaborated Example. Quadratic Form.
  135. x = 0
  136.  
  137.  
  138. total = 0
  139.  
  140. for s in xrange(Ns):
  141.       for t in xrange(Nt):
  142.             total += v[s]*M[s,t]*v[t]
  143.  
  144. x = total
  145.  
  146.  
  147.  
  148.  
  149. x = np.einsum("s,st,t->", v, M, v)
  150.  
  151. # 12. Elaborated example. Batched outer product.
  152.  
  153. R = np.empty((NB,ni,nj))
  154. for B in xrange(NB):
  155.       for i in xrange(Ni):
  156.             for j in xrange(Nj):
  157.                    total = 0
  158.                    
  159.                    
  160.                    total          += P[B,i]*Q[B,j]
  161.                    
  162.                    R[B,i,j] = total
  163.  
  164.  
  165.  
  166.  
  167. R = np.einsum("Bi,Bj->Bij", P, Q)
  168.  
  169. # 13. Natural consequences of einsum definition.
  170. #     Requirements on size of individual axes.
  171. C =            np.einsum("ik,kj->ij", A, B)
  172.  
  173.  
  174.  
  175. assert A.shape == (Ni,Nk)
  176. assert B.shape ==         (Nk,Nj)
  177. assert C.shape ==                 (Ni,Nj)
  178.  
  179. #     Requirement for identical size of certain axes due to
  180. #     shared index label.
  181. #         Example 1: Matrix Multiplication
  182. C =            np.einsum("ik,kj->ij", A, B)
  183.  
  184.  
  185.  
  186. assert           A.shape[1] == B.shape[0]         #  == Nk
  187. assert           A.shape[0] == C.shape[0]         #  == Ni
  188. assert           B.shape[1] == C.shape[1]         #  == Nj
  189.  
  190. #         Example 2: Matrix Diagonal Extraction
  191. d =            np.einsum("ii->i", D)
  192.  
  193.  
  194.  
  195. assert           D.shape[0] == D.shape[1]         #  == Ni
  196. assert           D.shape[1] == d.shape[0]         #  == Ni
  197.  
  198. # 14: Format Strings. Rules.
  199.  
  200. #    Bad. Number of input index groups doesn't match number of
  201. #         arguments.
  202. np.einsum("ab,bc->ac", A)
  203.  
  204. #    Bad. Indexes must be ASCII upper/lowercase letters.
  205. np.einsum("012,1^%->:;?", A, B)
  206.  
  207. #    Bad. Argument 0 has 3 dimensions but only 2 indexes are
  208. #         given.
  209. A = np.random.normal(size = (2,3,4))
  210. B = np.random.normal(size = (4,5,6))
  211. np.einsum("ab,bcd->a", A, B)
  212.  
  213. #    Bad. One of the output indexes isn't in the set of all
  214. #         input indexes.
  215. np.einsum("ab,bc->acz", A, B)
  216.  
  217. #    Bad. Output has a repeated index.
  218. np.einsum("ab,bc->baa", A, B)
  219.  
  220. #    Bad. Mismatches in the sizes of input argument axes
  221. #         that are labelled with the same index.
  222. A = np.random.normal(size = (2,3,4))
  223. B = np.random.normal(size = (3,4,5))
  224. np.einsum("ckj,cqq->c", A, B)
  225.  
  226. assert      A.shape[0] == B.shape[0]          # ERROR: 2 != 3
  227. assert      B.shape[1] == B.shape[2]          # ERROR: 4 != 5
  228.  
  229. # 15: MLP Backprop done easily (stochastic version).
  230. #     h = sigmoid(Wx + b)
  231. #     y = softmax(Vh + c)
  232. Ni = 784
  233. Nh = 500
  234. No =  10
  235.  
  236. W  = np.random.normal(size = (Nh,Ni))  # Nh x Ni
  237. b  = np.random.normal(size = (Nh,))    # Nh
  238. V  = np.random.normal(size = (No,Nh))  # No x Nh
  239. c  = np.random.normal(size = (No,))    # No
  240.  
  241. # Load x and t...
  242. x, t  = train_set[k]
  243.  
  244. # With a judicious, consistent choice of index labels, we can
  245. # express fprop() and bprop() extremely tersely; No thought
  246. # needs to be given about the details of shoehorning matrices
  247. # into np.dot(), such as the exact argument order and the
  248. # required transpositions.
  249. #
  250. # Let
  251. #
  252. #     'i' be the input  dimension label.
  253. #     'h' be the hidden dimension label.
  254. #     'o' be the output dimension label.
  255. #
  256. # Then
  257.  
  258. # Fprop
  259. ha    = np.einsum("hi, i -> h", W, x) + b
  260. h     = sigmoid(ha)
  261. ya    = np.einsum("oh, h -> o", V, h) + c
  262. y     = softmax(ya)
  263.  
  264. # Bprop
  265. dLdya = y - t
  266. dLdV  = np.einsum("h , o -> oh", h, dLdya)
  267. dLdc  = dLdya
  268. dLdh  = np.einsum("oh, o -> h ", V, dLdya)
  269. dLdha = dLdh * sigmoidgrad(ha)
  270. dLdW  = np.einsum("i,  h -> hi", x, dLdha)
  271. dLdb  = dLdha
  272.  
  273. # 16: MLP Backprop done easily (batch version).
  274. #     But we want to exploit hardware with a batch version!
  275. #     This is trivially implemented with simple additions
  276. #     to np.einsum's format string, in addition to the usual
  277. #     averaging logic required when handling batches. We
  278. #     implement even that logic with einsum for demonstration
  279. #     and elegance purposes.
  280. batch_size = 128
  281.  
  282. # Let
  283. #     'B' be the batch  dimension label.
  284. #     'i' be the input  dimension label.
  285. #     'h' be the hidden dimension label.
  286. #     'o' be the output dimension label.
  287. #
  288. # Then
  289.  
  290. # Fprop
  291. ha    = np.einsum("hi, Bi -> Bh", W, x) + b
  292. h     = sigmoid(ha)
  293. ya    = np.einsum("oh, Bh -> Bo", V, h) + c
  294. y     = softmax(ya)
  295.  
  296. # Bprop
  297. dLdya = y - t
  298. dLdV  = np.einsum("Bh, Bo -> oh", h, dLdya) / batch_size
  299. dLdc  = np.einsum("Bo     -> o ",    dLdya) / batch_size
  300. dLdh  = np.einsum("oh, Bo -> Bh", V, dLdya)
  301. dLdha = dLdh * sigmoidgrad(ha)
  302. dLdW  = np.einsum("Bi, Bh -> hi", x, dLdha) / batch_size
  303. dLdb  = np.einsum("Bh     -> h ",    dLdha) / batch_size
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement