用TensorFlow來寫計(jì)算過程已經(jīng)有很多人在github給出了教程和代碼。推薦這個(gè)TensorFlow代碼 Github163,提供了多種學(xué)習(xí)的tensorflow代碼實(shí)現(xiàn)。
這里不會(huì)說logistic regression的具體內(nèi)容,內(nèi)部的算法原理參考李航老師的《統(tǒng)計(jì)機(jī)器學(xué)習(xí)》的邏輯回歸與最大熵一章和Speech and Language Processing的第六章MAXIMUM ENTROPY MODELS,兩者我都覺得講得很棒。
在TensorFlow里這個(gè)模型用5行代碼就能夠完成:
model = tf.add(tf.matmul(X, w), b)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(model, Y))
train = tf.train.GradientDescentOptimizer(0.1).minimize(cost)
邏輯回歸的參數(shù)是w和b,構(gòu)造計(jì)算節(jié)點(diǎn)完成計(jì)算w*x+b,應(yīng)用到對應(yīng)的logistic函數(shù)里,【這里為什么要叫和最大熵扯上關(guān)系,其實(shí)一般書上的數(shù)學(xué)解釋都不從最大熵入手,而利用最大熵原理去推導(dǎo)也能夠得到一致的形式,所以說softmax是正對形式上的叫法,而有的時(shí)候和maximum entropy有關(guān)是從數(shù)學(xué)上的角度來看這個(gè)模型的,兩者不沖突?!坷锰荻认陆祦韮?yōu)化損失。
如果是單純是利用最大似然等公式寫一個(gè)邏輯斯諦回歸比較麻煩的一件事,用了TensorFlow之后可以看到被簡化了非常多,基本不涉及到數(shù)學(xué)公式了。。。(用BaiduML可能更夸張,連代碼都不用寫,給他數(shù)據(jù)選個(gè)模型就好了)
這里用的數(shù)據(jù)是MNIST,在http:///tutorial/logreg.html可以看到這個(gè)數(shù)據(jù)集應(yīng)用到邏輯斯蒂回歸的基本解釋和代碼,這里的數(shù)據(jù)和開始給出的tutorial的數(shù)據(jù)都是MNIST,但是否一樣就不知道了,那個(gè)哥們的是有幾個(gè)文件好像,logreg.html里是使用的是Theano來完成的,也就是上一代的工具了??梢钥纯从兄诶斫?。
拿完整的帶注釋的代碼來講:
# -*- encoding=utf-8 -*-
# author: Ian
# create on: 2015-11-17
# des: use TensorFlow to make log regression works
import gzip
import os
import sys
import numpy as np
import cPickle
import tensorflow as tf
class LogisticRegression(object):
def __init__(self):
self.X = tf.placeholder("float", [None, 784])
self.Y = tf.placeholder("float", [None, 10])
self.W = tf.Variable(tf.random_normal([28 * 28, 10], stddev=0.01))
self.b = tf.Variable(tf.zeros([10, ]))
self.model = self.create_model(self.X, self.W, self.b)
# logistic and cal error
self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(self.model, self.Y))
# gradient descent method to minimize error
self.train = tf.train.GradientDescentOptimizer(0.1).minimize(self.cost)
# calculate the max pos each row
self.predict = tf.argmax(self.model, 1)
def create_model(self, X, w, b):
# wx + b
return tf.add(tf.matmul(X, w), b)
def load_data(self):
f = gzip.open('mnist.pkl.gz', 'rb')
train_set, valid_set, test_set = cPickle.load(f)
f.close()
return train_set, valid_set, test_set
def dense_to_one_hot(self, labels_dense, num_classes=10):
# ont hot copy from https://github.com/nlintz/TensorFlow-Tutorials
# also can use sklearn preprocessing OneHotEncoder()
num_labels = labels_dense.shape[0]
index_offset = np.arange(num_labels) * num_classes
labels_one_hot = np.zeros((num_labels, num_classes))
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
return labels_one_hot
def run(self):
train_set, valid_set, test_set = self.load_data()
train_X, train_Y = train_set
test_X, test_Y = test_set
train_Y = self.dense_to_one_hot(train_Y)
test_Y = self.dense_to_one_hot(test_Y)
sess = tf.Session()
init = tf.initialize_all_variables()
sess.run(init)
for i in range(100):
for start, end in zip(range(0, len(train_X), 128), range(128, len(train_X), 128)):
sess.run(self.train, feed_dict={self.X: train_X[start:end], self.Y: train_Y[start:end]})
print i, np.mean(np.argmax(test_Y, axis=1) == sess.run(self.predict, feed_dict={self.X: test_X, self.Y: test_Y}))
sess.close()
if __name__ == '__main__':
lr_model = LogisticRegression()
lr_model.run()
基本的步驟注釋已經(jīng)給出,tf.nn.softmax_cross_entropy_with_logits這個(gè)函數(shù)在接受Y參數(shù)的時(shí)候是對每一個(gè)label,size需要和class num一樣大的,原始的數(shù)據(jù)集labels是[0-9]的標(biāo)注,需要進(jìn)行onehot預(yù)處理。
onehot可能需要解釋一下:onehot也是一位有效編碼,有N個(gè)狀態(tài),我們使用N個(gè)位來表示對應(yīng)的狀態(tài),例如,可能取值為[0,1,2],使用100,010,001來表示,例如
>>> from sklearn import preprocessing
>>> enc = preprocessing.OneHotEncoder()
>>> enc.fit([[0, 0], [1, 1], [1, 2]])
>>> enc.transform([[0, 2]]).toarray()
array([[ 1., 0., 0., 0., 1.]])
第一個(gè)元素的取值為01,第二個(gè)為012,所以是2+3=5位。計(jì)算節(jié)點(diǎn)的流向也在剛剛開始給出。
原文45
|