<深度学习入门与TensorFlow实践> - 笔记 II

举报
黄生 发表于 2022/08/21 11:54:04 2022/08/21
【摘要】 继续随机梯度下降法,回到广告数据,以TV,radio为自变量,以sales为因变量,没有截距,所有观测点作为训练数据。先要对自变量进行标准化,对因变量进行中心化。标准化后所有自变量的均值是0,方差是1。中心化后因变量的均值是0。这样做可以让梯步下降法的数值更加稳定,更容易找到合适的初始值和学习步长。一个标准化的方法就是让数据的每一列减去该列的均值,然后除以该列的样本标准差(sd(x)sd(x...

继续随机梯度下降法,

回到广告数据,以TV,radio为自变量,以sales为因变量,没有截距,所有观测点作为训练数据。
先要对自变量进行标准化,对因变量进行中心化
标准化后所有自变量的均值是0,方差是1。中心化后因变量的均值是0。
这样做可以让梯步下降法的数值更加稳定,更容易找到合适的初始值和学习步长。

一个标准化的方法就是让数据的每一列减去该列的均值,然后除以该列的样本标准差( s d ( x ) sd(x) ):

image.png

中心化,只要前面的一步即可:

c e n t e r e d _ y = y y ˉ centered\_y = y - \bar{y}

#标准化和中心化。然后随机梯度下降

x=ad.iloc[:,0:2].values
y=ad.iloc[:,3].values
scaled_x=(x-np.mean(x,axis=0,keepdims=True))/ \
            np.std(x,axis=0,keepdims=True)
centered_y=y-np.mean(y)

lr=0.1
w=np.zeros(2)
w_record=[w.copy()]
for iter in range(5):
    total_loss=0
    for i in range(len(scaled_x)):
        pred=np.sum(scaled_x[i]*w)
        total_loss+=((pred-centered_y[i])**2)/2
        delta=(pred-centered_y[i])
        w-=lr*(delta*scaled_x[i])
        w_record.append(w.copy())
    print('Loss: %0.5f'%(total_loss/(i+1)))
    print(w)
Loss: 1.98663
[3.46941055 3.19188802]
Loss: 1.62702
[3.46941055 3.19188802]
Loss: 1.62702
[3.46941055 3.19188802]
Loss: 1.62702
[3.46941055 3.19188802]
Loss: 1.62702
[3.46941055 3.19188802]

随机梯度下降法中,每次迭代只使用一个观测点,计算的梯度随机性比较大,所以有时候参数的值不会朝着最小损失的方向移动。

全数据梯度下降法Full Gradient Dscent)在计算梯度时会用到所有观测点,因此算出来的梯度会比较稳定。

image.png

全数据梯度下降法的代码例子就不看了。

image.png

这两种梯度下降法各自的特点是如此的鲜明,所以必定还会有一种中庸调和的方法,那就是批量随机梯度下降法Batch Stochastic Gradient Descent)。

他在计算梯度时,既不是使用单个观测点,也不是使用所有观测点,而是每次用一小部分观测点,在实际中常用的有16,32~1024个观测点,根据内存和模型规模选取合适的。

image.png

批量随机梯度下降法的代码例子也不看了。


学习步长 α \alpha 是一个很重要的参数。
如果太小,算法会收敛的很慢。
如果太大,容易造成算法不收敛,甚至发散。

自变量的标准化,和因变量的中心化,是建立深度学习模型常用的数据预处理方法。
他们的好处,是不仅可以让梯度下降法的数值表现的更加稳定,还有助于我们找到合适的初始值和步长。

image.png

在梯度下降法中,学习步长batch size需要事先给定,而不像参数w一样通过最小化损失函数得到,这类参数在机器学习中叫做超参数

接下来是介绍线性分类模型,logistic模型。回归模型分类模型的主要区别就是因变量y的数据类型不一样。

image.png

在处理实际问题的时候,根据这个区别,我们就可以选择建立回归模型还是分类模型:

image.png


这里有一个数据集,它的内容包含:信用卡余额、每月收入、是否违约。

%config InlineBackend.figure_format='retina'

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

def loadDataSet():
    x=[];y=[]
    f=open('./Default.txt')
    for line in f.readlines():
        lineArr=line.strip().split()
        x.append([float(lineArr[0]),float(lineArr[1])])
        y.append(lineArr[2])
    return np.array(x),y
x,y=loadDataSet()
print(y)

#Yes > 1, No > 0
y01=np.zeros(len(y))
for i in range(len(y)):
    if y[i] == 'Yes':
        y01[i]=1
y=y01
print(y)
['Yes', 'Yes',... 'No', 'No']
[1. 1. ... 0. 0.]
plt.scatter(x[y==0,0],x[y==0,1],label='No')
plt.scatter(x[y==1,0],x[y==1,1],s=80,label='Yes')
plt.xlabel('Balance',fontsize=16)
plt.ylabel('Income',fontsize=16)
plt.legend()
plt.show

image.png

从上图中可以看到,信用卡余额相对于每月收入来说,对还款违约的影响更大。
一般模型不会直接预测某信用卡用户是否违约,而是预测其违约的概率,表示为P(Default|Balance,Income),因为它的值在0和1之间,所以如果直接用类似线性回归模型的方式是不行的,需要对加权和进行变换。即:

image.png

f ( x ) = 1 1 + e x f(x)=\frac{1}{1+e^{-x}} 函数在统计学文献中称为logistic函数,在机器学习文献中称为sigmoid函数

a=np.linspace(-10,10,100)
plt.plot(a,1/(1+np.exp(-a)),linewidth=3)
plt.axvline(x=0,linestyle='--',color='m',linewidth=2)
plt.axhline(y=0.5,linestyle='--',color='m',linewidth=2)
plt.show

image.png

根据这个函数的图形,预测值和x值的关系看的就比较清楚。基本上就是x大于0时,预测值为1的概率大于0.5,而概率大于0.5,可以认为是分类值1。


在logistic模型中,损失函数可以定义为

image.png

其中 p i p_{i} 表示第i个观测点的预测概率值, y i y_i 表示第i个观测点的因变量的值(0或者1)

观察 y i y_i 等于零或者一的情况,可以做出下的变换

image.png

接下来实在是看不下去了,还有求偏导数的主要技巧用到了链式法则,还有其他的太难看了。所以这一小部分跳过。

接下来的内容是深度神经网络。

image.png

观察箭头的方向,代表了处理的流程。通过线性回归模型和生物神经元的类比,可以将线性模型称作一个只包含一个神经元的神经网络。
同样的,logistic模型也可以用来进行类比,下图代表的就是预估y等于1的概率的处理过程:
image.png

他与线性回归模型的不同点在于:Logistic模型对输入值加权,并使用sigmoid函数做了非线性处理。

为什么需要深度神经网络呢?下面用代码和例子来说明。


#定义sigmoid函数
def sigmoid(input):
    return 1.0/(1+np.exp(-input))

#通过随机梯度下降法估计参数
def logit_model(x,y,w,b,lr=0.1):
    for iter in range(60):
        loss=0
        for i in range(len(x)):
            pred=sigmoid(np.dot(x[i:i+1],w)+b)
            loss+=-(y[i:i+1]*np.log(pred)+\
                    (1-y[i:i+1])*np.log(1-pred))
            delta=pred-y[i:i+1]
            b-=lr*delta
            w-=lr*np.dot(x[i:i+1].T,delta)
            
        if (iter%10==9 or iter==59):
            print('Loss:'+str(loss))
    return w,b
    
#给定w,b时,计算模型预测值
def predict_logit_model(x,w,b):
    pred=[]
    for i in range(len(x)):
        tmp=sigmoid(np.dot(x[i:i+1],w)+b)
        if tmp>0.5:
            tmp=1
        else:
            tmp=0
        pred.append(tmp)
    return np.array(pred)

#画x的散点图
def scatter_simple_data(x,y):
    plt.scatter(x[y==0,0],x[y==0,1],label='0',marker='o')
    plt.scatter(x[y==1,0],x[y==1,1],s=80,label='1',marker='s')
    plt.legend()
    plt.xlabel('x1',fontsize=16)
    plt.ylabel('x2',fontsize=16)
    plt.show()

#画logistic模型的决策边界
def plot_decision_bound(x,y,w,b):
    x1=np.linspace(0,1,100)
    x2=(-b-x1*w[0])/w[1]
    plt.scatter(x[y==0,0],x[y==0,1],label='0',marker='o')
    plt.scatter(x[y==1,0],x[y==1,1],s=80,label='1',marker='s')
    plt.plot(x1,x2)
    plt.legend()
    plt.xlabel('x1',fontsize=16)
    plt.ylabel('x2',fontsize=16)
#构造第1组数据
def createDataSet_1():
    x=np.array([[0,0],[0,1],[1,0],[1,1]])
    y=np.array([1,1,0,0])
    return x,y

x,y=createDataSet_1()
scatter_simple_data(x,y)

image.png

np.random.seed(4)
w=np.random.normal(size=2) #从标准正态分布中随机生成初始权重
b,lr=0,0.1
w,b=logit_model(x,y,w,b,lr)

pred=predict_logit_model(x,w,b)
print('因变量的真实值:'+str(y))
print('因变量的预测值:'+str(pred))
Loss:[2.13470015]
Loss:[1.67673736]
Loss:[1.36190603]
Loss:[1.13485563]
Loss:[0.96600061]
Loss:[0.83689858]
因变量的真实值:[1 1 0 0]
因变量的预测值:[1 1 0 0]
plot_decision_bound(x,y,w,b)

image.png

logistic模型找到的这条线,预测都正确。
但是,如果不是这么“完美”的分布呢,比如这样的第2组数据,就不是一条线能泾渭分明的分开的:

#构造第2组数据
def createDataSet_2():
    x=np.array([[0,0],[0,1],[1,0],[1,1]])
    y=np.array([1,0,0,1])
    return x,y

x,y=createDataSet_2()
scatter_simple_data(x,y)

w=np.array([0,-0.3])
b,lr=0,0.1
w,b=logit_model(x,y,w,b,lr)

pred=predict_logit_model(x,w,b)
print('因变量的真实值:'+str(y))
print('因变量的预测值:'+str(pred))

plot_decision_bound(x,y,w,b)

image.png

Loss:[2.88349771]
Loss:[2.8812307]
Loss:[2.8797981]
Loss:[2.87874047]
Loss:[2.87800035]
Loss:[2.87749129]
因变量的真实值:[1 0 0 1]
因变量的预测值:[1 0 1 1]

image.png

可以看到logistic模型找到的线,有一个右下角的原点预测错误。4个当中1个错误。这个是情理之中,别说机器,让你只画一条决策线,能进行正确的预测划分,你也画不出来。

但是如果可以让你画2条线,那就没什么问题。那么对机器来说,又应该怎么做呢?

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。