def test_DiffOperations(reset_NodeDict): x = Var('x') y = Var('y') fx = VSF('f', x) fy = VSF('f', y) gx = VSF('g', x) gy = VSF('g', y) gfx = VSF('g', fx) zero = Val(0) one = Val(1) assert (zero == Val(0)) assert (zero != one) assert (fx != gx) assert (unicode(Var('x')) == 'x') assert (unicode(fx) == 'f(x)') assert (unicode(gfx) == 'g(f(x))') assert (unicode(Mul(fx, gx)) == 'f(x)*g(x)') assert (unicode(Mul(fx, gy)) == 'f(x)*g(y)') assert (unicode(Mul(gfx, gy)) == 'g(f(x))*g(y)') z = '0.0' i = '1.0' assert (unicode(Mul( fx, gx).diff_no_simplify(x)) == u"f`(x)⨯%s⨯g(x)+f(x)⨯g`(x)⨯%s" % (i, i)) assert (unicode(Mul( fx, gy).diff_no_simplify(x)) == u"f`(x)⨯%s⨯g(y)+f(x)⨯g`(y)⨯%s" % (i, z)) assert (unicode(fx.diff_no_simplify(x)) == u"f`(x)⨯%s" % i) assert (unicode(gfx.diff_no_simplify(x)) == u"g`(f(x))⨯f`(x)⨯%s" % i) assert (unicode(gfx.diff_no_simplify(y)) == u"g`(f(x))⨯f`(x)⨯%s" % z) assert(unicode(Mul(gfx,gy).diff_no_simplify(x)) ==\ u'g`(f(x))⨯f`(x)⨯%s⨯g(y)+g(f(x))⨯g`(y)⨯%s'%(i,z)) assert(unicode(Mul(gfx,gy).diff_no_simplify(y)) ==\ u'g`(f(x))⨯f`(x)⨯%s⨯g(y)+g(f(x))⨯g`(y)⨯%s'%(z,i))
def test_DiffKnownFunctions(reset_NodeDict): x = Var('x') fx = VSF('sin', x) dfx = fx.diff(x) dfx.cache() #dfx is used in dgfx again. Forgetting to cache fx may casue subtle errors. assert (dfx.expression() == 'cos(x)') gfx = VSF('exp', Mul(Val(3), fx)) dgfx = gfx.diff(x) assert (dgfx.expression() == u'exp(3*sin(x))⨯3⨯cos(x)') #Caching top expressions only is enough gfx.cache() dgfx.cache() for v in [1.0, 2.0, 14.2, 5.1, 5.72341]: x.val = v assert (dfx.val == np.cos(v)) assert (gfx.val == np.exp(3 * np.sin(v))) #Allow slight difference for complex numpy expressions. np.testing.assert_allclose(dgfx.val, np.exp(3 * np.sin(v)) * 3 * np.cos(v), rtol=1e-10, atol=0) hfx = VSF('log', fx) dhfx = hfx.diff(x) assert (dhfx.expression() == u'1/(sin(x))⨯cos(x)') hx = VSF('log', Add(fx, VSF('exp', x))) dhx = hx.diff(x) assert (dhx.expression() == u'1/(sin(x)+exp(x))⨯{cos(x)+exp(x)}')
def test_outer(reset_NodeDict): ran = lambda x: np.random.random(x) vx = ran(4) vy = ran(3) assert np.all(np.outer(vx, vy) == vx.reshape(4, 1) * vy.reshape(1, 3)) x = Var('x', vx) y = Var('y', vy) assert np.all(Outer(x, y).val == np.outer(vx, vy))
def test_variables_of_expressions(): ran=lambda x : np.random.random(x)-0.5 x=Var('x',ran((1,4))) y=Var('y',ran((1,4))) z=Var('z',ran((1,4))) expr=Add(Add(Add(x,y),x),z) for var in ['x','y','z'] : assert var in expr.variables assert list(expr.variables).count(var)==1
def test_ExpressionMutations(reset_NodeDict): x = Var('x') fx = VSF('sin', x, np.sin) gx = VSF('exp', x, np.exp) #Mutable expression need to be cached. fx.cache() gx.cache() v = 1.0 for v in [1.0, 0.5, 0.1]: x.val = v assert (fx.val == np.sin(v)) assert (gx.val == np.exp(v))
def test_matrix_circle_times_operations(reset_NodeDict): va = np.matrix([[1, 2, 3], [2, 3, 4]]) vb = np.matrix([[2, 3, 4], [3, 2, 1]]) vx = np.matrix([5, 1, 2]) vy = np.matrix([[5], [1], [2]]) a, b, x, y = Var('a', va), Var('b', vb), Var('x', vx), Var('y', vy) with pytest.raises(ValueError): va * vx with pytest.raises(ValueError): va.dot(vx) with pytest.raises(ValueError): Mul(a, x).val assert_all(va * vy == va.dot(vy)) assert_all(va * vy == Mul(a, y).val) assert_all(va * vy == [[13], [21]]) assert_all(CTimes(a, a).val == np.array([[1, 4, 9], [4, 9, 16]])) assert_all(CTimes(a, b).val == np.array([[2, 6, 12], [6, 6, 4]])) assert_all(CTimes(b, a).val == np.array([[2, 6, 12], [6, 6, 4]])) vd = np.matrix([1, 3]) ve = np.matrix([[1], [2], [4]]) vf = np.matrix([1, 2, 4]) d, e, f = Var('d', vd), Var('e', ve), Var('f', vf) with pytest.raises(ValueError): Mul(d, e).val assert (np.all(CTimes(d, e).val == np.array([[1, 3], [2, 6], [4, 12]]))) assert (np.all(CTimes(e, d).val == np.array([[1, 3], [2, 6], [4, 12]]))) with pytest.raises(ValueError): CTimes(d, f).val
def test_concatenation(reset_NodeDict): vx = np.array([5, 1, 2]) vy = np.array([1, 3, 2]) x = Var('x', vx) y = Var('y', vy) xpy = Concat(x, y) dfdx = xpy.diff(x) ones = Val(np.ones(3)) zero = Val(np.zeros(3)) oz = Concat(ones, zero) assert_all(dfdx.val == oz.val) #It is a bit tricky; it is limitation of current implementation. assert oz is not dfdx dfdx.cache() ones = Val(np.ones(3)) zero = Val(np.zeros(3)) oz = Concat(ones, zero) assert oz is dfdx
def test_ParentsSettingOfCache(): x = Var('x') fx = VSF('sin', x) dfx = fx.diff(x) gfx = VSF('exp', Mul(Val(3), fx)) dgfx = gfx.diff(x) dgfx.cache() assert fx in x.parents and dfx in x.parents for expr in dgfx.children: assert dgfx in expr.parents
def InitialRNN(): ran = lambda x: np.random.random(x) - 0.5 n = 200 h0, w0, b0, u0 = Var('h0'), Var('w0'), Var('b0'), Var('u0') vh0, vw0, vb0, vu0 = ran((n, 1)), ran((n, 2 * n)), ran((n, 1)), ran((n, 1)) h0.val, w0.val, b0.val, u0.val = vh0, vw0, vb0, vu0 u0.val /= np.abs(u0.val).sum() #L1 normalization. return RecursiveNN(w0, b0, u0)
def test_Equality(reset_NodeDict): x = Var('x') y = Var('y') fx = VSF('f', x) #Each expressions are reused if cached. assert (x is not Var('x')) x.cache() assert (x is Var('x')) fx.cache() assert (fx is VSF('f', x)) assert (Var('x') == x) assert (Val(1) == Val(1)) #Values are simplified to scalar when possible: assert (Val(1) == Val(np.array([1]))) assert (Val(1) == Val(np.array([[1]])))
def test_SimplifyZeroAndOne(reset_NodeDict): assert (IsIdentity(Val(1))) assert (Mul(Val(1), Val(1)).simplify() == Val(1)) assert (Mul(Mul(Val(1), Val(1)), Mul(Val(1), Mul(Val(1), Mul(Val(1), Val(1))))).simplify() == Val(1)) assert (Mul(Mul(Val(1), Val(1)), Mul(Val(1), Mul(Val(1), Mul(Val(1), Val(0))))).simplify() == Val(0)) x = Var('x') y = Var('y') fx = VSF('f', x) fy = VSF('f', y) gx = VSF('g', x) gy = VSF('g', y) hx = VSF('h', x) gfx = VSF('g', fx) zero = Val(0) one = Val(1) assert (unicode(Mul(one, Add(x, y))) == '1*{x+y}') assert (Mul(one, Add(x, y)).expression() == '1*{x+y}') assert (unicode(Mul(one, Add(x, y)).simplify()) == 'x+y') assert (Add(fx, zero).simplify() == fx) assert (Mul(fx, zero).simplify() == zero) assert (Mul(fx, one).simplify() == fx) assert (Mul(zero, gy).simplify() == zero) assert (Mul(gx, Mul(fx, zero)).simplify() == zero) assert (Mul(gy, Mul(gx, Mul(fx, zero))).simplify() == zero) assert (unicode(fx.diff(x)) == 'f`(x)') assert (unicode(Mul(gfx, gy).diff(x)) == u'g`(f(x))⨯f`(x)⨯g(y)') assert (unicode(Mul(gfx, gy).diff(y)) == u'g(f(x))⨯g`(y)') assert (unicode(Mul(hx, Mul(gx, fx))) == u'h(x)*g(x)*f(x)') assert (unicode(Mul(hx, Mul( gx, fx)).diff(x)) == u'h`(x)⨯g(x)*f(x)+h(x)⨯{g`(x)⨯f(x)+g(x)⨯f`(x)}') assert (unicode(Mul(hx, Mul(gx, fx)).diff(y)) == '0.0')
def _RNN(): ran = lambda x: np.random.random(x) - 0.5 phrase_expr = lambda W_mat, word_left, word_right, bias: VSF( 'tanh', Add(Dot(W_mat, Concat(word_left, word_right)), bias)) W = declareAndCache(u'W') W.val = ran((200, 400)) bias = declareAndCache(u'b', ) bias.val = ran((200, )) u_score = declareAndCache(u'u_score', ) u_score.val = ran((200, )) assert Var(u'W') is W phrase_w1w2 = lambda w1, w2: phrase_expr(W, w1, w2, bias) w1 = declareAndCache(u'w1') w2 = declareAndCache(u'w2') w1.val, w2.val = ran(200), ran(200) score = lambda phrase: Dot(u_score, phrase) #score(phrase_w1w2(w1,w2)).diff(W) print unicode(phrase_w1w2(w1, w2).diff(W))
def test_IterativeParsing(reset_NodeDict): ran = lambda x: np.random.random(x) - 0.5 n = 5 h0, w0, b0, u0 = Var('h0'), Var('w0'), Var('b0'), Var('u0') vh0, vw0, vb0, vu0 = ran((n, 1)), ran((n, 2 * n)), ran((n, 1)), ran((n, 1)) h0.val, w0.val, b0.val, u0.val = vh0, vw0, vb0, vu0 rnn = RecursiveNN(w0, b0, u0) the, cat, on, hat = Word('the'), Word('cat'), Word('on'), Word('hat') nodes = [the, cat, on, the, hat] assert nodes[0] is nodes[3] sentence, score = rnn.combineToSentence(nodes) print unicode(sentence), score.val print sentence print '%s' % sentence
def test_Transpose(reset_NodeDict): vx = np.matrix([5, 1, 2]) vy = np.matrix([1, 3, 2]).T x = Var('x', vx) y = Var('y', vy) fy = VSF('f', y) gx = VSF('g', x) fygx = Mul(fy, gx) assert (unicode(Transpose(fygx).simplify()) == u'[f(y)*g(x)]ᵀ') assert (unicode(Transpose(Var('z', 2)).simplify()) == 'z') assert (Transpose(Var('z', 2)).val == 2) assert_all(Transpose(x).val == vx.T) assert_all(Transpose(Transpose(x)).val == x.val) y.val = vy.T xyt = Mul(x, Transpose(y)) assert (unicode(Transpose(xyt)) == u'[x*yᵀ]ᵀ') assert (xyt.val == 12)
def test_GradientNumericalChecks(reset_NodeDict): ran = lambda x: np.random.random(x) - 0.5 n = 5 h0, w0, b0, u0 = Var('h0'), Var('W0'), Var('b0'), Var('u0') vh0, vw0, vb0, vu0 = ran((n, 1)), ran((n, 2 * n)), ran((n, 1)), ran((n, 1)) h0.val, w0.val, b0.val, u0.val = vh0, vw0, vb0, vu0 rnn = RecursiveNN(w0, b0, u0) the, cat, on, a, hat = Word('the'), Word('cat'), Word('on'), Word( 'a'), Word('hat') the_cat = rnn.combineTwoNodes(the, cat) a_hat = rnn.combineTwoNodes(a, hat) the_cat_on = rnn.combineTwoNodes(the_cat, on) the_cat_on_a_hat = rnn.combineTwoNodes(the_cat_on, a_hat) assert unicode(the_cat_on_a_hat) == u'(((the,cat),on),(a,hat))' #assert unicode(rnn.score(the_cat))==u'u0ᵀ⋅tanh(W0⋅{the⊕cat}+b0)' #assert unicode(rnn.score(the_cat_on))==u'u0ᵀ⋅tanh(W0⋅{tanh(W0⋅{the⊕cat}+b0)⊕on}+b0)' score = rnn.score(the_cat_on_a_hat) score.cache() s0 = score.val gradient = Differentiation(score, w0) #TODO:Check parents management and makes the for-loop works. #for i in range(10): diff = 0.001 * ran(w0.val.shape) ds_grad = np.sum(diff * gradient.val) tmp = gradient.val np.random.shuffle(tmp) ds_ran = np.sum(diff * tmp) w0.val += diff s1 = score.val ds = s1 - s0 print ds_grad / ds, ds_ran / ds assert (abs(ds - ds_grad) < abs(ds - ds_ran)) np.testing.assert_allclose(ds, ds_grad, rtol=1e-2, atol=0) assert score.isContain(w0) assert not score.isContain(Var('xx'))
def test_Evaluation(reset_NodeDict): vx = np.array([1.0, 2.0, 3.0]).reshape(1, 3) vy = np.array([2.0, 3.0, 4.0]).reshape(3, 1) vz = np.array([3.0, 5.0, 7.0]).reshape(1, 3) x = Var('x') x.val = vx y = Var('y', vy) z = Var('z', vz) with pytest.raises(ValueError): Dot(x, Var('t', vy.T)).val xy = Mul(x, y) assert (unicode(xy) == 'x*y') assert_all(xy.val == vx.dot(vy)) x_plus_z = Add(x, z) assert (unicode(x_plus_z) == 'x+z') assert_all(x_plus_z.val == vx + vz) assert_all(CTimes(xy, z).val == CTimes(z, xy).val) assert_all(CTimes(xy, z).val == vx.dot(vy) * vz) s0 = 1.57 s = Var('s', s0) fs = VSF('cos', s, np.cos) assert (unicode(fs) == 'cos(s)') assert (fs.val == np.cos(s0))
def _SimplePhrase(reset_NodeDict): W_left_init = Var('W_left', [0, 0, 0, 0]) W_right_init = Var('W_right', [0, 0, 0, 0]) bias_init = Var('bias', [1, 1]) rnn = RecursiveNN(W_left_init, W_right_init, bias_init) merge = rnn.combineTwoNodes the = Word('The') cat = Word('cat') assert (not hasattr(Val(11), 'expression')) assert (hasattr(the, 'expression')) assert (the.expression() == 'w2v(The)') assert (unicode(the) == 'The') the_cat = merge(the, cat) assert (unicode(the_cat) == '(The,cat)') assert ( the_cat.expression() == 'tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)') assert (unicode(the_cat.diff_no_simplify(Var('W_left'))) == '') assert (the_cat.diff(Var('W_left')).expression() == 'tanh`(W_left*w2v(The)+W_right*w2v(cat)+bias)*w2v(The)') the_cat_is = merge(the_cat, Word('is')) assert (unicode(the_cat_is) == '((The,cat),is)') assert ( the_cat_is.expression() == 'tanh(W_left*tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_right*w2v(is)+bias)' ) expected='tanh`(W_left*tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_right*w2v(is)+bias)*'+ \ '(tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_left*tanh`(W_left*w2v(The)+W_right*w2v(cat)+bias)*w2v(The))' assert (the_cat_is.diff(Var('W_left')).expression() == expected) assert (unicode(merge(the_cat, merge(Word('is'), Word('cute')))) == '((The,cat),(is,cute))') the_cat_is_cute = merge(the_cat_is, Word('cute')) assert (unicode(the_cat_is_cute) == '(((The,cat),is),cute)') expected = 'tanh(W_left*tanh(W_left*tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_right*w2v(is)+bias)+W_right*w2v(cute)+bias)' assert (the_cat_is_cute.expression() == expected)
def test_Dot(): a = Var('A', ran((2, 3))) b = Var('b', ran((3, ))) ab = Dot(a, b) assert ab.val.shape == (2, ) assert ab.diff(b) == a
def test_GradientNumericalChecks(reset_NodeDict): ran = lambda x: np.random.random(x) - 0.5 x, y, a, b = Var('x'), Var('y'), Var('a'), Var('b') D, C, B, A = Var('D'), Var('C'), Var('B'), Var('A') #g:= x⋅C⋅sin(B⋅sin(A⋅y+a)+b) g = Dot(Dot(x, C), VSF('sin', Add(Dot(B, VSF('sin', Add(Dot(A, y), a))), b))) g.cache() #0.01 is may not small enough for g=x⋅C⋅sin(B⋅sin(A⋅y+a)+b). scale = 0.001 for var in [B, A, y, a]: p = [] p_ran = [] for i in range(3): x.val, y.val, a.val, b.val = ran((1, 4)), ran((4, 1)), ran( (5, 1)), ran((6, 1)) #D,C,B,A = Var('D', ran((4,4))), Var('C', ran((4,6))), Var('B', ran((6,5))), Var('A', ran((5,4))) D.val, C.val, B.val, A.val = ran((4, 4)), ran((4, 6)), ran( (6, 5)), ran((5, 4)) gradient = Differentiation(g, var) gradient.cache() var0 = var.val delta = NormalizedMatrix(ran(var.val.shape), scale) rand_grad = gradient.val.copy() np.random.shuffle(rand_grad) rand_grad = NormalizedMatrix(ran(gradient.val.shape), gradient.val.sum()) dg_ran = np.sum(delta * rand_grad) dg_grad = np.sum(delta * gradient.val) g0 = g.val var.val = var0 + delta g1 = g.val dg = g1 - g0 p.append(dg / dg_grad) p_ran.append(dg / dg_ran) p = np.array(p) p_ran = np.array(p_ran) precision = np.abs(np.mean(p) - 1) precision_ran = np.abs(np.mean(p_ran) - 1) assert precision < 10 * scale assert precision < precision_ran
def test_ReuseExistingExpressions(reset_NodeDict): ran = lambda x: np.random.random(x) - 0.5 x, y, a, b = Var('x'), Var('y'), Var('a'), Var('b') D, C, B, A = Var('D'), Var('C'), Var('B'), Var('A') x.val, y.val, a.val, b.val = ran((1, 4)), ran((4, 1)), ran((5, 1)), ran( (6, 1)) D.val, C.val, B.val, A.val = ran((4, 4)), ran((4, 6)), ran((6, 5)), ran( (5, 4)) xDy = Dot(x, Dot(D, y)) xDy.cache() assert Var('x') is xDy.x assert Dot(D, y).y is Var('y') assert Dot(D, y) is xDy.y xDy2 = Dot(Dot(x, D), y) tmp = Differentiation(xDy2, x) tmp2 = Differentiation(xDy2, x) assert tmp2 is not tmp tmp.cache() tmp2 = Differentiation(xDy2, x) assert tmp2 is tmp tmp3 = Differentiation(xDy, x) assert tmp3 is tmp f = Dot(Dot(x, C), Dot(B, VSF('sin', Add(Dot(A, y), a)))) f.cache() dfdy = Differentiation(f, y) dfdy2 = Differentiation(f, y) assert dfdy2 is not dfdy dfdy.cache() dfdy2 = Differentiation(f, y) assert dfdy2 is dfdy dfda = Differentiation(f, a) assert dfda.var is dfdy.var.x g = Dot(Dot(x, C), VSF('sin', Add(Dot(B, VSF('sin', Add(Dot(A, y), a))), b))) g.cache() assert g.y.var.x is f.y dgdA = Differentiation(g, A) dgdA.cache() dgdB = Differentiation(g, B) print unicode(dgdB) assert dgdB.y.var is f.y.y assert dgdA.x.var.x.x is dgdB.x.var
def test_MatrixDifferentiation_internal(reset_NodeDict): w = Var('w', [[1, 2], [2, 3]]) x, y, z = Var('x', 1), Var('y', [1, 2]), Var('z', [1, 2]) with pytest.raises(ValueError): _Diff(w, x, y, z)
def test_expressions_code_generation(): ran=lambda x : np.random.random(x)-0.5 x=Var('x',ran((1,4))) y=Var('y',ran((4,1))) a=Var('a',ran((5,1))) b=Var('b',ran((6,1))) D,C,B,A = Var('D', ran((4,4))), Var('C', ran((4,6))), Var('B', ran((6,5))), Var('A', ran((5,4))) ns={} f = Dot(Dot(x,C),Dot(B,VSF('sin',Add(Dot(A,y),a)))) assert f.code()=='np.dot(np.dot(x,C),np.dot(B,np.sin(np.add(np.dot(A,y),a))))' ns=Node.Compile('f',f, ns) assert ns['f'](A=A.val,B=B.val,C=C.val, a=a.val,x=x.val,y=y.val)==f.val g = Dot(Dot(x,C),VSF('sin',Add(Dot(B,VSF('sin',Add(Dot(A,y),a))),b))) assert g.code()=='np.dot(np.dot(x,C),np.sin(np.add(np.dot(B,np.sin(np.add(np.dot(A,y),a))),b)))' ns=Node.Compile('g',g, ns) assert ns['g'](A=A.val,B=B.val,C=C.val, a=a.val,b=b.val,x=x.val,y=y.val)==g.val h,w,b,u,w12 =Var('h'),Var('W'),Var('b'),Var('u'), Var('word12') phrase=VSF('tanh', Add(Dot(w, h), b)) score=Dot(u,phrase) assert phrase.code()=='np.tanh(np.add(np.dot(W,h),b))' assert score.code()=='np.dot(u,np.tanh(np.add(np.dot(W,h),b)))'
def test_CacheKnownValues(reset_NodeDict): x = Var('x') fx = VSF('cos', x, np.cos) gfx = VSF('exp', fx, np.exp) gfx.cache() exp_cos = lambda x: np.exp(np.cos(x)) for v in np.random.random(10): x.val = v assert (gfx.val == exp_cos(v)) for i in range(100): assert (gfx.val == exp_cos(v)) y = Var('y') hy = VSF('tanh', y, np.tanh) hy.cache() for v in np.random.random(10): y.val = v assert (hy.val == np.tanh(v)) gfx_hy = CTimes(gfx, hy) gfx_hy.cache() exp_cos_x_times_tanh_y = lambda x, y: exp_cos(x) * np.tanh(y) vx = 5.7 vy = np.array([1.1, 2.1, 0.5]) x.val = vx y.val = vy print gfx_hy.val / exp_cos_x_times_tanh_y(vx, vy) assert_all(gfx_hy.val == exp_cos_x_times_tanh_y(vx, vy)) print "Change x only:" #TODO: verify hy will not be evaluated, but use cache, instead. vx = 1.0 x.val = vx assert_all(gfx_hy.val == exp_cos_x_times_tanh_y(vx, vy)) print "Change y only:" #TODO: verify gfx will not be evaluated, but use cache, instead. vy = 1.0 y.val = vy assert_all(gfx_hy.val == exp_cos_x_times_tanh_y(vx, vy)) #Instance of Var must be single-assigned, #but it is not yet enforced by code. a = Var('a') b = Var('b') ab = Mul(a, b) ab.cache() assert (np.isnan(ab.val)) a.val = 1.0 assert (np.isnan(ab.val)) b.val = 2.0 assert (ab.val == 2.0)
def declareAndCache(name, val=None): var = Var(name, val) var.cache() return var
def test_VectorAndMatrixVariables(reset_NodeDict): ran = lambda x: np.random.random(x) - 0.5 x = Var('x', ran((1, 4))) y = Var('y', ran((4, 1))) a = Var('a', ran((5, 1))) b = Var('b', ran((6, 1))) D, C, B, A = Var('D', ran((4, 4))), Var('C', ran( (4, 6))), Var('B', ran((6, 5))), Var('A', ran((5, 4))) assert (x.val.shape == (1, 4)) assert IsZero(Differentiation(Dot(x, y), D)) assert IsZero(Differentiation(Dot(x, y), a)) assert unicode(Differentiation(Dot(x, y), y)) == u'xᵀ' assert unicode(Differentiation(Dot(x, y), x)) == u'yᵀ' xDy = Dot(x, Dot(D, y)) assert unicode(xDy) == u'x⋅D⋅y' assert unicode(Differentiation(xDy, y)) == u'[x⋅D]ᵀ' assert unicode(Differentiation(xDy, x)) == u'[D⋅y]ᵀ' xDy = Dot(Dot(x, D), y) assert unicode(xDy) == u'x⋅D⋅y' assert unicode(Differentiation(xDy, y)) == u'[x⋅D]ᵀ' assert unicode(Differentiation(xDy, x)) == u'[D⋅y]ᵀ' xCBAy = Dot(x, Dot(C, Dot(B, Dot(A, y)))) assert unicode(xCBAy) == u'x⋅C⋅B⋅A⋅y' assert unicode(Differentiation(xCBAy, x)) == u'[C⋅B⋅A⋅y]ᵀ' assert unicode(Differentiation(xCBAy, y)) == u'[x⋅C⋅B⋅A]ᵀ' xCBAy = Dot(Dot(x, C), Dot(B, Dot(A, y))) assert unicode(xCBAy) == u'x⋅C⋅B⋅A⋅y' assert unicode(Differentiation(xCBAy, x)) == u'[C⋅B⋅A⋅y]ᵀ' assert unicode(Differentiation(xCBAy, y)) == u'[x⋅C⋅B⋅A]ᵀ' xfy = Dot(x, VSF('sin', y)) assert unicode(xfy) == u'x⋅sin(y)' assert unicode(Differentiation(xfy, y)) == u'[x⨯[cos(y)]ᵀ]ᵀ' f = Dot(Dot(x, C), Dot(B, VSF('sin', Add(Dot(A, y), a)))) assert unicode(f) == u'x⋅C⋅B⋅sin(A⋅y+a)' assert unicode(Differentiation(f, y)) == u'[x⋅C⋅B⨯[cos(A⋅y+a)]ᵀ⋅A]ᵀ' assert unicode(Differentiation(f, a)) == u'[x⋅C⋅B⨯[cos(A⋅y+a)]ᵀ]ᵀ' g = Dot(Dot(x, C), VSF('sin', Add(Dot(B, VSF('sin', Add(Dot(A, y), a))), b))) assert unicode(g) == u'x⋅C⋅sin(B⋅sin(A⋅y+a)+b)' assert unicode(Differentiation(g, x)) == u'[C⋅sin(B⋅sin(A⋅y+a)+b)]ᵀ' assert unicode(Differentiation(g, b)) == u'[x⋅C⨯[cos(B⋅sin(A⋅y+a)+b)]ᵀ]ᵀ' assert unicode(Differentiation( g, a)) == u'[x⋅C⨯[cos(B⋅sin(A⋅y+a)+b)]ᵀ⋅B⨯[cos(A⋅y+a)]ᵀ]ᵀ' assert unicode(Differentiation( g, y)) == u'[x⋅C⨯[cos(B⋅sin(A⋅y+a)+b)]ᵀ⋅B⨯[cos(A⋅y+a)]ᵀ⋅A]ᵀ' print unicode(Differentiation(g, A)) assert unicode(Differentiation( g, A)) == u'[x⋅C⨯[cos(B⋅sin(A⋅y+a)+b)]ᵀ⋅B⨯[cos(A⋅y+a)]ᵀ]ᵀ⨯yᵀ' assert unicode(Differentiation( g, B)) == u'[x⋅C⨯[cos(B⋅sin(A⋅y+a)+b)]ᵀ]ᵀ⨯[sin(A⋅y+a)]ᵀ' assert unicode(Differentiation(g, C)) == u'xᵀ⨯[sin(B⋅sin(A⋅y+a)+b)]ᵀ' dgdx = Differentiation(g, x) dgdb = Differentiation(g, b) dgda = Differentiation(g, a) dgdy = Differentiation(g, y) delta = NormalizedMatrix(ran(x.val.shape), 0.01)