线性回归模型
1.线性回归
- 优点:建模速度快、计算量小、系数容易理解和解释。
- 缺点:模型容易欠拟合、对异常值敏感。
- 原理:对给定数据集,其中,,d为特征维度,m为样本数量,即找到一个线性模型拟合之间的关系,以最简单的例子:用拟合yi,找到一个合适的w和b。
- 求解策略:最小二乘法即基于均方误差最小化的思想进行求解,使得找到一条直线,样本中所有的点到直线的欧氏距离之和最小。
- 求解方法:梯度下降和牛顿法等最优化算法。
2.延伸:对数几率回归
- 变回归任务为分类任务,需要找到一个单调可微的函数将分类任务的真实标记y和线性回归的预测值联系起来。如:在每个特征乘上一个回归系数再求和得到,然后将回归方程带入sigmoid函数中得到:就可以得到一个二分类的分类模型。
- 求解策略:极大似然估计方法得到模型中的参数,公式推导略。
- 求解方法同线性回归。
- 推广到多分类问题,就是拆解成若干个二分类任务求解。
3.最优化算法
- 梯度下降法:梯度下降法的优化思想是用当前位置负梯度方向作为搜索方向,因为该方向为当前位置的最快下降方向,所以也被称为是”最速下降法“,梯度下降法在接近最优解的区域收敛速度明显变慢,所以利用梯度下降法求解需要很多次的迭代。梯度下降算法在每次更新回归系数时都会遍历整个数据集,当数据集小时效果很好,但是数据集太多时时间复杂度就太高了,所以它的优化办法时采用随机梯度下降,每次随机选取一个样本进行随机梯度下降。随机梯度下降也会有缺点:SGD的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
- 牛顿法:使用函数f(x)的泰勒级数的前面几项来寻找方程f (x) = 0的根,牛顿法最大的特点就在于它的收敛速度很快,因为从本质上讲牛顿法是一种利用高阶导数进行收敛的方法,可以看出下一步参数变化的趋势,但是伴随着的计算量也会增加。拟牛顿法我暂时未用到过,所以不谈了。
- 启发式优化算法:包括像PSO、EA算法以及一些多目标优化框架,这个不是几句话能说清的,但我刚好有学过这方面知识,所以会在之后单列一章介绍。
4.代码实现
第一部分代码是基于sklearn学习框架实现的,较为简单,也比较实用,将逻辑回归用于实现深度学习中的入门例子:手写数字的识别。
import numpy as np
import tensorflow as tf
#是minist数据集,可以去网上下一下
import input_data
from sklearn.datasets import load_digits
#以one-hot编码读入训练数据
minist=input_data.read_data_sets('//minist//data', one_hot=True)
mnist = fetch_mldata('MNIST original')
#利用read_data_sets下载minist数据集并且分好类
trainimg=minist.train.images
trainlabel=minist.train.labels
testimg=minist.test.images
testlabel=minist.test.lables
print('Minist Loaded')
#tf.palceholder:用于得到传递进来的真实训练样本,占位符
#images_placeholder = tf.placeholder(tf.float32, shape=[batch_size, IMAGE_PIXELS])
#labels_placeholder = tf.placeholder(tf.int32, shape=[batch_size])
x=tf.placeholder("float",[None,784])
y=tf.placeholder("float",[None,10])
#tf.Variable:主要在于一些可训练变量(trainable variables),比如模型的权重(weights,W)或者偏差值(bias)
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
#softmax模型可以用来给不同的对象分配概率,用于多分类
actv=tf.nn.softmax(tf.matmul(x, W) + b)
#cost function,这是对数似然损失函数的均值
cost=tf.reduce_mean(-tf.reduce_sum(y*tf.log(actv),reduction_indices=1))
learning_rate=0.01
#定义一个GradientDescentOptimizer的求解策略和求解目标minimize(cost)为一个tf运算
optm=tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
#预测结果
pred=tf.equl(tf.argmx(actv,1),tf.argmax(y,1))
#精度
accr=tf.reduce_mean(tf.cast(pred,"float"))
init=tf.globle_variables_initializer()
#初始一个session
sess=tf.Session
sess.run(init)
training_epochs=50
batch_size=100
display_step=5
for epoch in range(training_epochs):
avg_cost=0
num_bacth=int(minist.train.num_examples/batch_size)
for i in range(num_batch):
#划分每次训练的训练batch和测试batch
batch_xs,batch_ys=minist.train.next_batch(batch_size)
#运算session,给tf占位变量喂值
sess.run(optm,feed_dict={x: batch_xs, y: batch_ys})
feeds={x: batch_xs, y: batch_ys}
avg_cost +=sess.run(cost,feed_dict=feeds)
if epoch % display_step == 0:
feeds_train = {x: batch_xs, y: batch_ys}
feeds_test = {x: mnist.test.images, y: mnist.test.labels}
train_acc = sess.run(accr, feed_dict=feeds_train)
test_acc = sess.run(accr, feed_dict=feeds_test)
print ("Epoch: %03d/%03d cost: %.9f train_acc: %.3f test_acc: %.3f"
% (epoch, training_epochs, avg_cost, train_acc, test_acc))
print ("DONE")
第二部分是脱离库实现的,是机器学习实战中的一个预测病马死亡率的例子。
import numpy as np
import random
def sigmoid(inX):
return 1.0/(1+exp(-inX))
#定义随机梯度上升法
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n=shape(dataMatrix)
weights = oens(n)
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(1.0+i+j)+0.01
#随机生成下一个实数,它在 [x, y) 范围内。
randIndex = int(random.uniform(0,len(dataIndex)))
#改进之一:随机产生一个样本
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex]-h
#改进之二:权重更新
weights = weights+alpha*error*dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights
def classifyVector(inX,weights):
prob=sigmoid(sum(inX*weights))
if prob > 0.5: return 1.0
else: return 0.0
def colicTest():
frTrain = open('horseColicTraining.txt')
frTest = open('hourseColicTest.txt')
#这里是把训练集分成特征和标签,同时把特征从字符串提取出来转换成列表
trainingSet=[]
trainingLabels=[]
for line in frTrain.readlines():
#分标签和去两边的空格
currLine = line.strip().split('\t')
lineArr=[]
for i in range (21):
lineArr.append(float(currLine[i]))
trainingSet.append(lineArr)
trainingLabels,append(float(currLine[21]))
#随机梯度上升法得到最佳权重
trainWeights = stocGradAscent1(array(trainingSet),trainingLabels,500)
errorCount=0;numTestVec=0.0
for line in frTest.readlines():
numTestVect += 1.0
currLine = line.strip().split('\t')
lineArr = []
for i in range(21):
lineArr.append(float(currLine[i]))
#得到测试标签结果
if int(classifyVector(array(lineArr),trainWeights)) != int(currLine(21)):
errorCount += 1
errorRate = (float(errorCount)/numTestVec)
print('the error rate of this test is: %f' %errorRate)
return errorRate
#求十次精确度的平均值
def multiTest():
numTest = 10
errorSum = 0.0
for k in range(numTests):
errorSum += colicTest()
print('after %d iterations the average error rate is : %f' %(numTest, errorSum/float(numTest)))