Theano 实例:Logistic 回归¶

In [1]:

  1. %matplotlib inline
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import theano
  5. import theano.tensor as T
  1. Using gpu device 0: GeForce GTX 850M

sigmoid 函数¶

一个 logistic 曲线由 sigmoid 函数给出:s(x) = \frac{1}{1+e^{-x}}

我们来定义一个 elementwise 的 sigmoid 函数:

In [2]:

  1. x = T.matrix('x')
  2. s = 1 / (1 + T.exp(-x))
  3. sigmoid = theano.function([x], s, allow_input_downcast=True)

这里 allow_input_downcast=True 的作用是允许输入 downcast 成定义的输入类型:

In [3]:

  1. sigmoid([[ 0, 1],
  2. [-1,-2]])

Out[3]:

  1. array([[ 0.5 , 0.7310586 ],
  2. [ 0.26894143, 0.11920293]], dtype=float32)

其图像如下所示:

In [4]:

  1. X = np.linspace(-6, 6, 100)
  2. X = X[np.newaxis,:]
  3.  
  4. plt.figure(figsize=(12,5))
  5.  
  6. plt.plot(X.flatten(), sigmoid(X).flatten(), linewidth=2)
  7.  
  8. # 美化图像的操作
  9. #=========================
  10. plt.grid('on')
  11. plt.yticks([0,0.5,1])
  12.  
  13. ax = plt.gca()
  14. ax.spines['right'].set_color('none')
  15. ax.spines['top'].set_color('none')
  16.  
  17. ax.yaxis.set_ticks_position('left')
  18. ax.spines['left'].set_position(('data', 0))
  19.  
  20. plt.legend([r'$s(x)=\frac{1}{1+e^{-x}}$'], loc=0, fontsize=20)
  21. #=========================
  22.  
  23. plt.show()

09.09 Theano 实例:Logistic 回归 - 图1

sigmoid 函数与 tanh 函数的关系¶

sigmoid 函数与 tanh 之间有如下的转化关系:s(x)=\frac{1}{1+e^{-x}}=\frac{1+\tanh(x/2)}{2}

In [5]:

  1. s2 = (1 + T.tanh(x / 2)) / 2
  2.  
  3. sigmoid2 = theano.function([x], s2)
  4.  
  5. sigmoid2([[ 0, 1],
  6. [-1,-2]])

Out[5]:

  1. array([[ 0.5 , 0.7310586 ],
  2. [ 0.26894143, 0.11920291]], dtype=float32)

logistic 回归¶

简单的二元逻辑回归问题可以这样描述:我们要对数据点 $x = (x_1, …, x_n)$ 进行 0-1 分类,参数为 $w = (w_1, …, w_n), b$,我们的假设函数如下:

\begin{align}h_{w,b}(x) & = P(Y=1|X=x) \& = sigmoid(z) \& =\frac{1}{1 + e^{-z}}\\end{align}

其中

\begin{align}z & = x_1w_1 + … + x_nw_n + b\& = w^T x + b\\end{align}

对于一个数据点 $(x, y), y\in {0,1}$ 来说,我们的目标是希望 $h_{w,b}(x)$ 的值尽量接近于 $y$。

由于数值在 0-1 之间,我们用交叉熵来衡量 $h_{w,b}(x)$ 和 $y$ 的差异:

- y \log(h{w,b}(x)) - (1-y) \log(1-h{w,b}(x))

对于一组数据,我们定义损失函数为所有差异的均值,然后通过梯度下降法来优化损失函数,得到最优的参数 $w, b$。

实例¶

生成随机数据:

In [6]:

  1. rng = np.random
  2.  
  3. # 数据大小和规模
  4. N = 400
  5. feats = 784
  6.  
  7. # D = (X, Y)
  8. D = (rng.randn(N, feats), rng.randint(size=N, low=0, high=2))

定义 theano 变量:

In [7]:

  1. x = T.matrix('x')
  2. y = T.vector('y')
  3.  
  4. # 要更新的变量:
  5. w = theano.shared(rng.randn(feats), name='w')
  6. b = theano.shared(0., name='b')

定义模型:

In [8]:

  1. h = 1 / (1 + T.exp(-T.dot(x, w) - b))

当 $h > 0.5$ 时,认为该类的标签为 1:

In [9]:

  1. prediction = h > 0.5

损失函数和梯度:

In [10]:

  1. cost = - T.mean(y * T.log(h) + (1 - y) * T.log(1 - h)) + 0.01 * T.sum(w ** 2) # 正则项,防止过拟合
  2. gw, gb = T.grad(cost, [w, b])

编译训练和预测函数:

In [11]:

  1. train = theano.function(inputs=[x, y],
  2. outputs=cost,
  3. updates=[[w, w - 0.1 * gw], [b, b - 0.1 * gb]],
  4. allow_input_downcast=True)
  5.  
  6. predict = theano.function(inputs=[x],
  7. outputs=prediction,
  8. allow_input_downcast=True)

In [12]:

  1. for i in xrange(10001):
  2. err = train(D[0], D[1])
  3. if i % 1000 == 0:
  4. print 'iter %5d, error %f' % (i, err)
  1. iter 0, error 19.295896
  2. iter 1000, error 0.210341
  3. iter 2000, error 0.126124
  4. iter 3000, error 0.124872
  5. iter 4000, error 0.124846
  6. iter 5000, error 0.124845
  7. iter 6000, error 0.124845
  8. iter 7000, error 0.124845
  9. iter 8000, error 0.124845
  10. iter 9000, error 0.124845
  11. iter 10000, error 0.124845

查看结果:

In [13]:

  1. print D[1]
  1. [0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1 0 0 1 1 0 0 0 0 1 0
  2. 1 1 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0 0 1 0 0 1 1 0 1 0 1 1 1 0 0 0 0 0 1 0 0
  3. 0 1 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 1 1 0 1 0
  4. 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1 0 1 1 0 0 0 0 0 1
  5. 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 1 1 1
  6. 1 0 1 0 0 1 0 0 1 1 1 1 0 1 0 1 0 1 1 1 1 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 0
  7. 1 0 1 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 1 1 1 1 1 0 0 0 1 1 1 0 1 1
  8. 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 1 1
  9. 0 0 1 1 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0
  10. 0 1 0 0 0 0 0 1 1 0 1 1 0 1 1 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1 1 1 0 1 0 0 1
  11. 0 1 0 1 0 0 1 0 0 1 1 1 0 1 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0]

In [14]:

  1. print predict(D[0])
  1. [0 0 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1 0 0 1 1 0 0 0 0 1 0
  2. 1 1 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0 0 1 0 0 1 1 0 1 0 1 1 1 0 0 0 0 0 1 0 0
  3. 0 1 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 1 0 1 0 0 1 0 0 1 0 1 1 1 1 0 1 0
  4. 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1 0 1 1 0 0 0 0 0 1
  5. 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 1 1 1
  6. 1 0 1 0 0 1 0 0 1 1 1 1 0 1 0 1 0 1 1 1 1 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 0
  7. 1 0 1 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 1 1 1 1 1 0 0 0 1 1 1 0 1 1
  8. 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 1 1
  9. 0 0 1 1 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0
  10. 0 1 0 0 0 0 0 1 1 0 1 1 0 1 1 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1 1 1 0 1 0 0 1
  11. 0 1 0 1 0 0 1 0 0 1 1 1 0 1 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0]

原文: https://nbviewer.jupyter.org/github/lijin-THU/notes-python/blob/master/09-theano/09.09-logistic-regression-.ipynb