Theano

  • Theano是一個Python函式庫,允許使用者定義,最佳化與評估數學表達式。
    • 機器學習依函數可分為幾類:
      • 判別函數(分類問題):找出可區別不同類別的邊界函數。
      • 迴歸函數(迴歸問題):找出資料點間的趨勢。
      • 生成函數:找出生成資料的機率函數。
    • Theano的主要功能是以符號定義函數,自動微分後,再將資料代入找出函數的參數得到機器學習的模型。

symbolic function

  • 函數中變數的加、減、乘、除或是其它運算,在正常情形下(例如非1/0),變數可以視為純量(scalar)、向量(vector)、矩陣(matrix)等,而這些變數均為張量(tensor)的特例。
    • 張量(tensor)是一個可用來表示在一些向量、純量和其他張量之間的線性關係的多線性函數,這些線性關係的基本例子有內積、外積、線性映射以及笛卡兒積。
    • 因此建立函數時,只要指定變數為那一種類別,可使用theano建出對應的函數。
import theano.tensor as T
from theano import (function, pp)
import numpyt as np

x = T.dscalar('x') # 宣告純量符號變數x, 預設type為double
print (type(x)) # theano.tensor.var.TensorVariable
print(x.type)   # TensorType(float64, scalar)
print (x.type is T.dscalar) # True

y = T.dscalar('y') # 宣告純量符號變數y, 預設type為double

# symbolic expression
z = x + y
print(pp(z)) # 'x+y'

# compile function([inputs], outputs), 第一次編譯時會花不少時間
f = function([x, y], z)

# call function
print(f(1,2)) # array(3.0)
print(f(3,4)) # array(7.0)
print (np.allclose(f(16.3, 12.1), 28.4)) # True
  • 如果將 x,y x,y 變數指定為matrix時,即為矩陣的加法如下:
import theano.tensor as T
from theano import function
import numpy as np

x = T.dmatrix('x')
y = T.dmatrix('y')
# symbolic expression
z = x + y

# compile function
f = function([x, y], z)

# call function
print(f(np.array([[1, 2], [3, 4]]), np.array([[10, 20], [30, 40]])))

# array([[ 11.,  22.],
#       [ 33.,  44.]])
  • 可用的型態如下:
    • byte: bscalar, bvector, bmatrix, brow, bcol, btensor3, btensor4
    • 16-bit integers: wscalar, wvector, wmatrix, wrow, wcol, wtensor3, wtensor4
    • 32-bit integers: iscalar, ivector, imatrix, irow, icol, itensor3, itensor4
    • 64-bit integers: lscalar, lvector, lmatrix, lrow, lcol, ltensor3, ltensor4
    • float: fscalar, fvector, fmatrix, frow, fcol, ftensor3, ftensor4
    • double: dscalar, dvector, dmatrix, drow, dcol, dtensor3, dtensor4
    • complex: cscalar, cvector, cmatrix, crow, ccol, ctensor3, ctensor4

相同輸入、多重輸出

  • function可連結到相同輸入,但不同輸出的多個函數
import theano
import theano.tensor as T

a, b = T.dmatrices('a', 'b')
diff = a - b
abs_diff = abs(diff)
diff_squared = diff**2

f = theano.function([a, b], [diff, abs_diff, diff_squared])
res = f([[1, 1], [1, 1]], [[0, 1], [2, 3]])

print(res[0]) # array([[ 1.,  0.],[-1., -2.]])
print(res[1]) # array([[ 1.,  0.],[ 1.,  2.]]),
print(res[2]) # array([[ 1.,  0.],[ 1.,  4.]])]

函數輸入可使用預設值

  • In class可設定function中參數的預設值
    • 也可以像dict替變數取名
from theano import In
from theano import function
import theano.tensor as T

x, y = T.dscalars('x', 'y')
z = x + y
f = function([x, In(y, value=1)], z)
print (f(33)) # array(34.0)
print( f(33, 2)) # array(35.0)
from theano import In
from theano import function
import theano.tensor as T

x, y, w = T.dscalars('x', 'y', 'w')
z2 = (x+y)*w 
f2 = function([x, In(y, value=1), In(w, value=2, name='w_by_name') ], z2)

print(f2(33)) # array(68.0)
print(f2(33,2)) # array(70.0)
print(f2(33, w_by_name=1)) # array(34.0)
print(f2(33, w_by_name=1, y=0)) # array(33.0)

Example: logistic function

Logistic function: s(x)=11+ex s(x) = \frac{1}{1+e^{-x}}
  • 加、減、乘、除計算在theano中均為elementwise的計算。
import theano
import theano.tensor as T
x = T.dmatrix('x')
s = 1 / (1 + T.exp(-x))
logistic = theano.function([x], s)

print (logistic([[0, 1], [-1, -2]]))
#array([[ 0.5       ,  0.73105858],
#       [ 0.26894142,  0.11920292]])
  • s(x)=11+ex=1+tanh(x/2)2 s(x) = \frac{1}{1 + e^{-x}} = \frac{1+ \tanh(x/2)}{2}.
s2 = (1 + T.tanh(x / 2)) / 2
logistic2 = theano.function([x], s2)
print (logistic2([[0, 1], [-1, -2]]))
#array([[ 0.5       ,  0.73105858],
#       [ 0.26894142,  0.11920292]])

shared variable

  • shared variable可被多個函數共同使用
    • 為non-symbolic與symblic的混合體
    • 可使用.get_value()取值
    • 使用.set_value()設值
  • Updates to shared variables can sometimes be done more quickly using in-place algorithms.
  • Theano has more control over where and how shared variables are allocated, which is one of the important elements of getting good performance on the GPU.
import theano.tensor as T
from theano import (shared, function)

state = shared(0)
inc = T.iscalar('inc')
accumulator = function([inc], state, updates=[(state, state+inc)])

print (state.get_value()) # 0
accumulator(1) # array(0), 此為state更新前的值
print (state.get_value()) # 1
accumulator(300) # array(1), 此為state更新前的值
print (state.get_value()) # 301

state.set_value(-1)
accumlator(3) # array(-1)
print (state.get_value()) # 2


# 多函數共用變數
decrementor = function([inc], state, updates=[(state, state-inc)])
decremetor(2) # array(2)
print (state.get_value())   # 0
  • function中的updates的用法為list of pairs of the form (shared-variable, new expression)
    • 其意義為只要function被執行時,則shared variable之值(.value)會更新為new expression的計算值

results matching ""

    No results matching ""