编程实现对率回归,并给出西瓜数据集3.0@上的结果。
对率回归即逻辑回归,可以看做没有隐藏层的,用sigmoid做激活函数,crossentropy做cost(不加regularization)的神经网络。
本题用theano实现,调参时,learning rate 设为1,更大则cost会出现震荡,迭代次数设为10000可收敛,但是,训练效果并不好,最高准确率也只有70%。简单分析,根据前面knn和决策树画的分类面,可以看出这个问题不是线性可分的,因此逻辑回归在这里不太适用。
第一次用theano,还是简单记录下
theano中有符号变量的概念,无实值,类似C语言,必须先声明其类型;表达式的概念,并没有做计算;函数的概念,定义好输入输出,输出一般是表达式,输入是与输出相关的变量(不要多也不要少),传入参数后,theano将会编译表达式(包含各种优化,时间较长),然后带入计算。
此外,函数中还可以有updates参数,形式为一对对的tuple,每对tuple由欲更新的变量,及更新的值组成。因为符号变量是无实值的,无法更新,这里没法用,于是有shared的概念,shared符号变量是有实值的。updates意义是,每次函数调用完后,updates参数中的tuple都发生一次更新。虽然其他方法也可以实现updates,但推荐使用updates,因为它涉及到一些theano的底层优化,例如减少gpu和cpu的通信,降低内存拷贝的时间。
theano还有自动求导功能,theano.grad(),以及一些在神经网络中常用的函数,softmax,交叉熵等。
具体实例可参考代码:
# coding: utf-8 import numpy as np import theano.tensor as T import theano import numpy.random as rng from theano.tensor.nnet import sigmoid, binary_crossentropy file = open('西瓜数据集3.csv'.decode('utf-8')) data = [raw.strip('\n').split(',') for raw in file] X = [[float(raw[-3]), float(raw[-2])] for raw in data[1:]] Y = [1 if raw[-1]=='是' else 0 for raw in data[1:]] feats = len(X[0]) lrate = 1 maxturn = 10000 x = T.dmatrix('x') y = T.vector('y') w = theano.shared(rng.normal(size=feats), name='w') b = theano.shared(rng.randn(), name='b') z = T.dot(x, w) + b p = sigmoid(z) cost = binary_crossentropy(p, y).mean() gw, gb = theano.grad(cost, [w, b]) pred_res = p > 0.5 fit = theano.function(inputs=[x, y], outputs=[cost, gw, gb], updates=((w, w-lrate*gw), (b, b-lrate*gb))) predict = theano.function(inputs=[x], outputs=[pred_res]) for i in range(maxturn): print fit(X, Y) train_res = predict(X)[0] print 'predict result:' print train_res print 'accuracy:' print float(sum([Y[i]==train_res[i] for i in range(len(Y))])) / len(Y)