Deeplearning——Logistics回归

资料来源:1、博客:http://binweber.top/2017/09/12/deep_learning_1/#more——转载,修改更新
    

 基本概念

逻辑回归:
  logistic回归又称logistic回归分析,是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域。例如,探讨引发疾病的危险因素,并根据危险因素预测疾病发生的概率等。
 
回归分析:
  回归分析是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。运用十分广泛,回归分析按照涉及的变量的多少,分为一元回归和多元回归分析;按照因变量的多少,可分为简单回归分析和多重回归分析;按照自变量和因变量之间的关系类型,可分为线性回归分析和非线性回归分析。如果在回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且自变量之间存在线性相关,则称为多重线性回归分析。
 

 本文例子

为了训练一个猫识别器,输入一张图片表示为特征向量 x ,并预测图片是否为猫,输出 y 为1(是)或0(不是)
 

 

我们称图片为非结构化数据,但在计算机中,一张图片以RGB方式编码时,它是以Red、Green、Blue三基色组成一个矩阵的方式进行储存的,这三个矩阵的大小和图片的大小相同 ,如图中每张猫图大小为64*64(pixeis:像素),那么三个矩阵中每个矩阵的大小即为64*64。
 
单元格中代表的像素值将用来组成一个N维的特征向量(单列 n 维)。在模式识别和机器学习中,一个特征向量用来表示一个对象。这个问题中,这个对象为猫或者非猫。
 
为了组成一个特征向量 x ,将每一种颜色的像素值进行拆分重塑,最终形成的特征向量 x 的维数为:${n_{x}} = 64*64*3 = 12288$(一列有12288个元素)。
 
特征向量x:
  
一个训练样本(一张图片数据)由一对 (x,y) 进行表示,其中 x 为$n_x$维特征向量,y是这个特征向量的标签,值为0或1。m个训练样本对将被表示为:

$$({x^{(1)}},{y^{(1)}}),({x^{(2)}},{y^{(2)}}),......,({x^{(m)}},{y^{(m)}})$$

定义矩阵X、Y,将输入的训练集(一组图片m张)中的x(1)x(1),x(2)x(2)等以及y(1)y(1),y(2)y(2)等分别堆叠在矩阵的列向量中:
$$X = [{{\rm{x}}^{(1)}},{x^{(2)}},......,{x^{(m)}}] $$
$$Y = [{{\rm{y}}^{(1)}},{y^{(2)}},......,{y^{(m)}}] $$
其中X为$n_x$行m列矩阵,Y为1行m列矩阵。
 
Python中即X.shape=($n_x$,m),Y.shape=(1,m)。(shape为numpy库中的函数,功能为获取矩阵长度)

 实现方案

Cat vs No-cat: 
给定以一个$n_x$维特征向量x表示的一张图片,这个算法将估计这张图中存在一只猫的概率,即 y = 1 的概率:
$$\hat y = P(y = 1|x),0 \le \hat y \le 1$$
我们希望能有一个函数,能够表示出$\hat y$,如果进行最简单的线性拟合的话,规定一个$n_x$维向量w和一个值b作为参数,可得到:
$$\hat y = {w^T}X + b$$
注意:w是一个与输入X同维度的列向量(转置后与X相乘得到的是一个实数),b为线性位置调整参数
由于$\hat y$是一个概率值,取值范围为[0 , 1],简单的进行线性拟合,得出的$\hat y$可能非常大,还可能为负值,
这时,便需要一个sigmoid函数来对它的值域进行约束,sigmoid函数的表达式为:
$$\sigma \left( z \right) = \frac{1}{{1 + {e^{ - z}}}}$$
函数图像为:

由函数图像可知,sigmoid函数有几个很好的性质:

- 当z趋近于正无穷大时,$\sigma z=1$
- 当z趋近于负无穷大时,$\sigma z=0$
- 当z = 0时,$\sigma z=0.5$
所以可以用sigmoid函数来约束$\hat y$的值域,此时:
$$\hat y = \sigma ({w^T}X + b) = \frac{1}{{1 + {e^{ - ({w^T}X + b)}}}}$$
 

 求参数w和b

参数w和b是通过样本数据训练获得的,给定一张图片(一个数据),我们会知道图片中是否有猫,即y = 1 或 y = 0,在算法中即称之为真实值,再把计算机通过算法计算出来的$\hat y$称之为预测值。
我们总希望预测值 $\hat y$ 与 y 的差异尽可能的小,甚至相同。也即是说,我们会定义一个衡量预测值 $\hat y$ 与真实值 y 之间差异的函数,通过求其差异最小化的解来得到 w 和 b 两个参数。
这个衡量预测值 $\hat y$ 与真实值 y 之间差异的函数就是损失函数(Loss Function):
$${\mathop{\rm L}\nolimits} (\hat y,y) = \frac{1}{2}{(\hat y - y)^2}$$
但在logistic回归中一般不使用这个损失函数,因为在训练参数过程中,使用这个损失函数将得到一个非凸函数,最终将存在很多局部最优解,这种情况下使用梯度下降(Gradient Descent)法无法找到最优解。所以在logistic回归中,一般采用log函数:
$${\mathop{\rm L}\nolimits} (\hat y,y) = - (y\log \hat y + (1 - y)\log (1 - \hat y))$$
log函数有如下性质:
- 当y = 1时,${\mathop{\rm L}\nolimits} (\hat y,y) = - y\log \hat y$
- 当y = 0时,${\mathop{\rm L}\nolimits} (\hat y,y) = - y\log (1 - \hat y)$
附:log函数默认以e为底(在python numpy中,log表示以e为底,log2、log10分别表示以2、10为底)
以上函数只是单个样本的差值,再定义一个函数来表示整个训练数据集差异的平均值,即成本函数(Cost Function)
$${\mathop{\rm J}\nolimits} (w,b) = \frac{1}{m}\sum\limits_{i = 1}^m {L({{\hat y}^i},{y^i})}$$
 
故,函数的最终形式是:
$${\text{J}}(w,b) =  - \frac{1} {m}\sum\limits_{i = 1}^m {(Y\log \frac{1} {{1 + {e^{ - ({w^T}X + b)}}}} + (1 - Y)\log (1 - \frac{1} {{1 + {e^{ - ({w^T}X + b)}}}}))} ,Y = 0,1$$
其中X,Y是从训练样本获得的数据,X是图像矩阵,Y是1或0。因此,我们可以通过求取J的最小值,来获得w和b这两个参数。最后在把这两个参数应用到$\hat y = \sigma ({w^T}X + b) = \frac{1}{{1 + {e^{ - ({w^T}X + b)}}}}$中作为最终的预测算法!!!

  使用梯度下降法来求得参数w和b,使得成本函数的最小化

参考学习:http://www.cnblogs.com/pinard/p/5970503.html 

  在微积分里面,对多元函数的参数求∂偏导数,把求得的各个参数的偏导数以向量的形式写出来,就是梯度。比如函数f(x,y), 分别对x,y求偏导数,求得的梯度向量就是${(\frac{{\partial f}}{{\partial x}},\frac{{\partial f}}{{\partial y}})^T}$,简称grad f(x,y)或者$\nabla f(x,y)$。对于在点(x0,y0)的具体梯度向量就是${(\frac{{\partial f}}{{\partial x_0}},\frac{{\partial f}}{{\partial y_0}})^T}$,或者$\nabla f(x_0,y_0)$,如果是3个参数的向量梯度,就是${(\frac{{\partial f}}{{\partial x}},\frac{{\partial f}}{{\partial y}},\frac{{\partial f}}{{\partial z}})^T}$,以此类推。

  那么这个梯度向量求出来有什么意义呢?他的意义从几何意义上讲,就是函数变化增加最快的地方。具体来说,对于函数f(x,y),在点(x0,y0),沿着梯度向量的方向就是$\nabla f(x_0,y_0)$的方向是f(x,y)增加最快的地方。或者说,沿着梯度向量的方向,更加容易找到函数的最大值。反过来说,沿着梯度向量相反的方向,也就是 $-\nabla f(x_0,y_0)$的方向,梯度减少最快,也就是更加容易找到函数的最小值。

  在机器学习算法中,在最小化损失函数时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数,和模型参数值(此处即是w和b)。

 

  在空间坐标中以w,b为轴画出损失函数J(w,b)的三维图像,可知这个函数为一个凸函数。为了找到合适的参数,先将w和b赋一个初始值,正如图中的小红点。在losgistic回归中,几乎任何初始化方法都有效,通常将参数初始化为零。随机初始化也起作用,但通常不会在losgistic回归中这样做,因为这个成本函数是凸的,无论初始化的值是多少,总会到达同一个点或大致相同的点(最优解)。梯度下降就是从起始点开始,试图在最陡峭的下降方向下坡,以便尽可能快地下坡到达最低点,这个下坡的方向便是此点的梯度值。

在二维图像中来看,顺着导数的方向,下降速度最快,用数学公式表达即是:

$$w: = w - a\frac{{\partial J(w,b)}}{{\partial w}}$$

$$b: = b - a\frac{{\partial J(w,b)}}{{\partial b}}$$

上述两式表示随时更新w与b的值。

  其中的”:=”意思为赋值,α为学习率,通常为一个小于1的数,用来控制梯度下降过程中每一次移动的规格,相当于迈的步子大小。α的不宜太小也不宜过大:太小会使迭代次数增加,容易陷入局部最优解;太大容易错过最优解。(a设置的值过小时,需要增加迭代次数,因为如果不增加迭代次数,可能还没有得到最优解就已经结束了,如同你要走一段固定长度的路,步子小了,就要多走几步)
 

待解决问题

1、如何把一张图片转换成矩阵数据?
2、算法中求$\hat y$只是用了最简单的线性拟合,是否有更好的拟合算法?
3、sigmoid函数中的 e 是否可以用更小或者更大的数来代替,对算法有什么影响,是更好了还是更差了?——已测试,测试结果见文末附录
 

Python实现

  总代码与输出

#logistic_regression.py

#导入用到的包
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage

#导入数据
def load_dataset():
    train_dataset = h5py.File("train_cat.h5","r") #读取训练数据,共209张图片
    test_dataset = h5py.File("test_cat.h5", "r") #读取测试数据,共50张图片
    
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #原始训练集(209*64*64*3)
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) #原始训练集的标签集(y=0非猫,y=1是猫)(209*1)
    
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) #原始测试集(50*64*64*3
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #原始测试集的标签集(y=0非猫,y=1是猫)(50*1)
    
    train_set_y_orig = train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #原始训练集的标签集设为(1*209)
    test_set_y_orig = test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #原始测试集的标签集设为(1*50)
    
    classes = np.array(test_dataset["list_classes"][:])
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes    #classes = [b'non-cat' b'cat']

#显示图片
def image_show(index,dataset):
    index = index
    if dataset == "train":
        plt.imshow(train_set_x_orig[index])
        print ("y = " + str(train_set_y[:, index]) + ", 它是一张" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' 图片。")
    elif dataset == "load_dataset_test":
        plt.imshow(test_set_x_orig[index])
        print ("y = " + str(test_set_y[:, index]) + ", 它是一张" + classes[np.squeeze(test_set_y[:, index])].decode("utf-8") +  "' 图片。")

#sigmoid函数
def sigmoid(z):
    s = 1.0/(1+np.exp(-z))
    return s

#初始化参数w,b
def initialize_with_zeros(dim):
    w = np.zeros((dim,1)) #w为一个dim*1矩阵
    b = 0    
    return w, b

#计算Y_hat,成本函数J以及dw,db
def propagate(w, b, X, Y):
    m = X.shape[1] #样本个数
    Y_hat = sigmoid(np.dot(w.T,X)+b)                                     
    cost = -(np.sum(np.dot(Y,np.log(Y_hat).T)+np.dot((1-Y),np.log(1-Y_hat).T)))/m #成本函数
    
    dw = (np.dot(X,(Y_hat-Y).T))/m
    db = (np.sum(Y_hat-Y))/m

    cost = np.squeeze(cost) #压缩维度    
    grads = {"dw": dw,
             "db": db} #梯度
    
    return grads, cost

#梯度下降找出最优解
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):#num_iterations-梯度下降次数 learning_rate-学习率,即参数ɑ
    costs = [] #记录成本值
    
    for i in range(num_iterations): #循环进行梯度下降
        grads, cost = propagate(w,b,X,Y)
        dw = grads["dw"]
        db = grads["db"]
        
        w = w - learning_rate*dw
        b = b - learning_rate*db
        
        if i % 100 == 0: #每100次记录一次成本值
            costs.append(cost)
        
        if print_cost and i % 100 == 0: #打印成本值
            print ("循环%i次后的成本值: %f" %(i, cost))
    
    params = {"w": w,
              "b": b} #最终参数值
    
    grads = {"dw": dw,
             "db": db}#最终梯度值
    
    return params, grads, costs

#预测出结果
def predict(w, b, X):
    m = X.shape[1] #样本个数
    Y_prediction = np.zeros((1,m)) #初始化预测输出
    w = w.reshape(X.shape[0], 1) #转置参数向量w
    
    Y_hat = sigmoid(np.dot(w.T,X)+b) #最终得到的参数代入方程
    
    for i in range(Y_hat.shape[1]):
        if Y_hat[:,i]>0.5:
            Y_prediction[:,i] = 1
        else:
            Y_prediction[:,i] = 0
    
    return Y_prediction

#建立整个预测模型
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False): 
                                                                            #num_iterations-梯度下降次数 learning_rate-学习率,即参数ɑ
    w, b = initialize_with_zeros(X_train.shape[0]) #初始化参数w,b

    parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost) #梯度下降找到最优参数
    
    w = parameters["w"]     #获得最终参数
    b = parameters["b"]     #获得最终参数
    
    Y_prediction_train = predict(w, b, X_train) #训练集的预测结果
    Y_prediction_test = predict(w, b, X_test) #测试集的预测结果
    
    train_accuracy = 100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100 #训练集识别准确度……abs——绝对值……mean——求均值
    test_accuracy = 100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100 #测试集识别准确度
    
    print("训练集识别准确度: {} %".format(train_accuracy))
    print("测试集识别准确度: {} %".format(test_accuracy))
    
    d = {"costs": costs,
         "Y_prediction_test": Y_prediction_test, 
         "Y_prediction_train" : Y_prediction_train, 
         "w" : w, 
         "b" : b,
         "learning_rate" : learning_rate,
         "num_iterations": num_iterations}
    
    return d

#初始化数据
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

m_train = train_set_x_orig.shape[0] #训练集中样本个数
m_test = test_set_x_orig.shape[0] #测试集总样本个数
num_px = test_set_x_orig.shape[1] #图片的像素大小

train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T #原始训练集的设为(12288*209)
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T #原始测试集设为(12288*50)

train_set_x = train_set_x_flatten/255. #将训练集矩阵标准化
test_set_x = test_set_x_flatten/255. #将测试集矩阵标准化

d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)

# 画出学习曲线
costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()

#学习率不同时的学习曲线
learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
    print ("学习率: " + str(i))
    models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = i, print_cost = False)
    print ('\n' + "-------------------------------------------------------" + '\n')

for i in learning_rates:
    plt.plot(np.squeeze(models[str(i)]["costs"]), label= str(models[str(i)]["learning_rate"]))

plt.ylabel('cost')
plt.xlabel('iterations')

legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()

out:

     

  解释:

     以上输出表示的是梯度下降次数为2000次,每次的下降步长分别为0.01,,0.001,0.0001的测试结果。

    由测试结果可知:

      1、循环n次后的成本值最小可以达到为0,而成本值表示的是预测值与真实值之间的差异程度,差异越小越好,所以达到为0 是最理想的结果。

      2、梯度下降的次数与下降步长需要协调改进,如同你要走一段固定的距离到达一个位置(即达到成本值最小,但具体不知道多少),步数多了,步子就要变小,步数少了,步子就要变大,但其实我们总有可能还没有到达那个位置或者超过了那个位置。以上测试中只减小了步长,很大可能是成本值还没有达到最小值。

      3、训练集的准确度是可以达到100%的,因为我们是通过训练集来确定出算法参数的,也即是说训练集的数据必然是接近100%拟合算法的,但测试集不是,测试集是我们确定了算法之后,再将经过算法得出的的预测值与真实值进行比较得到的结果。

函数汇总

  • load_dataset():return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes  #导入数据
  • image_show(index,dataset):return null    #显示图片
  • sigmoid(z):return s    #sigmoid函数
  • initialize_with_zeros(dim):return w, b    ##初始化参数w,b
  • propagate(w, b, X, Y):return grads, cost    ##计算Y_hat,成本函数J以及dw,db
  • optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):return params, grads, costs    #梯度下降找出最优解
  • predict(w, b, X):return Y_prediction    #预测出结果
  • model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):return d    #建立整个预测模型

    整个算法大概的流程:导入数据load_dataset()——通过训练数据计算$\hat y$propagate(w, b, X, Y),该函数会返回w和b的梯度值与成本函数cost公式——通过梯度下降法找出w和b的最优解optimize( ),返回最终的w和b参数——再把w和b参数赋给函数predict(),得出最终的预测算法

    以上流程部分嵌套,最后整合在model()中.

  部分代码分块解释

数据导入load_dataset():(加入了测试代码) 

#logistic_regression.py

#导入用到的包
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage

#导入数据
def load_dataset():
    train_dataset = h5py.File("train_cat.h5","r") #读取训练数据,共209张图片
    test_dataset = h5py.File("test_cat.h5", "r") #读取测试数据,共50张图片
    
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #原始训练集(209*64*64*3)
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) #原始训练集的标签集(y=0非猫,y=1是猫)(209*1)
    
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) #原始测试集(50*64*64*3
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #原始测试集的标签集(y=0非猫,y=1是猫)(50*1)
    
    train_set_y_orig = train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #原始训练集的标签集设为(1*209)
    test_set_y_orig = test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #原始测试集的标签集设为(1*50)
    
    classes = np.array(test_dataset["list_classes"][:])
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

#初始化数据
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()    #classes = [b'non-cat' b'cat']

#print("train_set_x_orig = " + str(train_set_x_orig))
#print("train_set_y = " + str(train_set_y))
#print("test_set_x_orig = " + str(test_set_x_orig))
#print("test_set_y = " + str(test_set_y))
print("classes = " + str(classes))
#print("type(train_set_x_orig) = " + str(type(train_set_x_orig)))
#print("type(train_set_y) = "  + str(type(train_set_y)))

  测试:

    print("type(train_set_y) = "  + str(type(train_set_y)))————输出:type(train_set_y) = <class 'numpy.ndarray'>:输出的数据是数组形式

    如下(图片数据的保存形式,即.h5文件内容):

            

        print("classes = " + str(classes))————输出: classes = [b'non-cat' b'cat']

    将数据还原为图片:    

#logistic_regression.py

#导入用到的包
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage

#导入数据
def load_dataset():
    train_dataset = h5py.File("train_cat.h5","r") #读取训练数据,共209张图片
    test_dataset = h5py.File("test_cat.h5", "r") #读取测试数据,共50张图片
    
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #原始训练集(209*64*64*3)
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) #原始训练集的标签集(y=0非猫,y=1是猫)(209*1)
    
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) #原始测试集(50*64*64*3
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #原始测试集的标签集(y=0非猫,y=1是猫)(50*1)
    
    train_set_y_orig = train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #原始训练集的标签集设为(1*209)
    test_set_y_orig = test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #原始测试集的标签集设为(1*50)
    
    classes = np.array(test_dataset["list_classes"][:])
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

#显示图片
def image_show(index,dataset):
    index = index
    if dataset == "train":
        plt.imshow(train_set_x_orig[index])
        print ("y = " + str(train_set_y[:, index]) + ", 它是一张" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' 图片。")
    elif dataset == "load_dataset_test":
        plt.imshow(test_set_x_orig[index])
        print ("y = " + str(test_set_y[:, index]) + ", 它是一张" + classes[np.squeeze(test_set_y[:, index])].decode("utf-8") +  "' 图片。")

#初始化数据
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

for i in range(0,50):
    plt.subplot(5,10,i+1)
    print(i+1)
    image_show(i,"load_dataset_test")
    
plt.show()
'''
for i in range(0,50):
    plt.subplot(5,10,i+1)
    print(i+1)
    image_show(i,"train")
    
plt.show()
'''

       输出:

            

     


 
附录:

关于最优解

  来看看梯度下降的一个直观的解释。比如我们在一座大山上的某处位置,由于我们不知道怎么下山,于是决定走一步算一步,也就是在每走到一个位置的时候,求解当前位置的梯度,沿着梯度的负方向,也就是当前最陡峭的位置向下走一步,然后继续求解当前位置梯度,向这一步所在位置沿着最陡峭最易下山的位置走一步。这样一步步的走下去,一直走到觉得我们已经到了山脚。当然这样走下去,有可能我们不能走到山脚,而是到了某一个局部的山峰低处。

  从上面的解释可以看出,梯度下降不一定能够找到全局的最优解,有可能是一个局部最优解。当然,如果损失函数是凸函数,梯度下降法得到的解就一定是全局最优解。

来源:http://www.cnblogs.com/pinard/p/5970503.html

 关于sigmoid函数中e的参数对算法结果的影响

   此处先把e看做一个变量a:$${\text{y}} = \frac{1} {{1 + {a^{ - x}}}}$$

  不同a值情况下的图像

        

  在程序中改变a的值进行测试

       

     以上的结果是在梯度下降次数为2000次,学习率为0.005的条件下测试的,可以看出,调整a的值是有助于改变识别准确度的。

   但也可以看到,在相同条件下,只改变a的值也会改变训练集的识别准确度,这又是为什么?

    我们知道训练集的识别准确度是可以通过梯度下降次数与学习率的调整最高达到100%的,那么再测试一下不同梯度下降次数条件下识别的准确度会有什么影响:

        

    由以上测试可以看出,训练集的识别准确度是可以达到100%的,但相应的却降低了测试集的识别准确度。

  我们知道训练集的准确度可以达到100%,完全是因为算法的参数就是从中计算出来的,也就是说,训练集的数据是近乎完全拟合算法的。但测试集不是,我们只是找了另外一些数据来对得到的这个算法进行测试,测试的过程类似于我们拿两张猫的图片来进行对比,一张已知是猫,一张未知,看他们的相似程度,相似程度高,就认为未知图片是猫。只是算法换成了数据,对比的也是数据。先把数据转换成函数,再通过这个函数来测试另外的数据。但就是这个数据转换成函数的结果,有很多种,优劣不一,它必然会省略掉一些信息,导致另外拿来测试的数据实际上应该是符合的却被测试为不符合。也即是再好的一个识别猫的算法,我们必然有可能拿一张不是猫的图像让它认为是猫,再拿一张是猫的图像让它认为不是猫(也即是对抗样本模型)。

  所以说,上面测试集识别准确度与训练集准确度的关系并不会是线性的,跟算法有很大的关系,但即使如此,测试集的识别准确度也在68%-74%之间了(梯度优化足够的前提下)。

 
posted @ 2017-10-22 08:30  韬小虾  阅读(2211)  评论(1编辑  收藏  举报