Linear regression with theano

목표

  1. 임의의 선형 TrueModel 을 정의하고,
  2. 이 모델에 적당한 랜덤값을 섞어 데이터를 생성한 후,
  3. 생성된 데이터를 잘 설명하는 선형 모델을 학습

해본다. 그냥 theano를 손에 조금 붙이기 위해 연습하는 것. 선형 모델로 생성한 데이터를 선형 모델로 추정하는 것이므로 사실상 별 의미는 없다. 그냥 kata.

True model 생성

In [1]:
A, B = 7.4, -3.1
def true_model(a, b):
    def _model(x):
        return a*x + b
    return _model

TRUE_MODEL = true_model(A, B)

$f(x) = Ax + B$ 가 가짜 데이터 생성에 사용할 진짜 모델이다.

가짜 데이터 생성

In [2]:
X = np.random.random(100) * 50
TRUE_Y = TRUE_MODEL(X)
OBSERVED_Y = TRUE_Y + [np.random.normal(0.0, 25.0) for _ in range(100)]

figsize(8,6)
scatter(X, OBSERVED_Y)
plot(X, TRUE_Y, color='red')
Out[2]:
[<matplotlib.lines.Line2D at 0x7f63900d33d0>]
/usr/local/lib/python2.7/dist-packages/matplotlib/font_manager.py:1236: UserWarning: findfont: Font family [&apos;monospace&apos;] not found. Falling back to Bitstream Vera Sans
  (prop.get_family(), self.defaultFamily[fontext]))

대강 내맘대로 생성해 보았다.

X, OBSERVED_Y 가 이제부터 볼 수 있는 데이터다.

Theano 로 모델링

In [3]:
from theano import tensor as T
import theano

x = T.dvector('x')
y = T.dvector('y')

a = theano.shared(
    value=np.random.random()-0.5,
    name='a')
b = theano.shared(
    value=np.random.random()-0.5,
    name='b')

print(a.get_value(), b.get_value())

squared_error = T.mean((y-(a*x+b))**2)

learning_rate = 0.0001
g_a = T.grad(cost=squared_error, wrt=a)
g_b = T.grad(cost=squared_error, wrt=b)
updates = [(a, a - learning_rate * g_a),
           (b, b - learning_rate * g_b)]

train_function = theano.function(
    inputs=[],
    outputs=a*x+b,
    updates=updates,
    givens = {
        x: X,
        y: OBSERVED_Y
    }
)
(-0.058619607058295387, 0.077335969611901589)

In [4]:
figsize(10,6)
fig, graphs = subplots(2, 4, sharex=True, sharey=True)
for i in range(32):
    if i % 4 == 0:
        row = int(i / 16)
        col = int(i / 4) % 4
        graphs[row, col].plot(X, X*a.get_value()+b.get_value(), color='blue')
        graphs[row, col].plot(X, TRUE_Y, color='red')
        #legend(["현재 상태", "숨어있는 진실"])
        legend(["Current", "Hidden Truth"])
    train_function()
In [5]:
train_a, train_b = a.get_value(), b.get_value()
def train_model(x):
    return train_a * x + train_b
print(train_a, train_b)
(7.3120235713156472, 0.30023375724411622)

In [6]:
figsize(8,6)

plot(X, TRUE_Y, color='red')
plot(X, train_model(X), color='blue')
scatter(X, OBSERVED_Y)

legend(["Hidden Truth", "Trained Model", "Observations"])
Out[6]:
<matplotlib.legend.Legend at 0x7f637ca3a910>
In [7]:
print("실제 모델: %.3fx + %.3f" % (A, B))
print("추정한 모델: %.3fx + %.3f" % (train_a, train_b))
실제 모델: 7.400x + -3.100
추정한 모델: 7.312x + 0.300

Comments