<深度学习入门与TensorFlow实践> - 笔记 II
继续随机梯度下降法,
回到广告数据,以TV,radio为自变量,以sales为因变量,没有截距,所有观测点作为训练数据。
先要对自变量进行标准化
,对因变量进行中心化
。
标准化后所有自变量的均值是0,方差是1。中心化后因变量的均值是0。
这样做可以让梯步下降法的数值更加稳定,更容易找到合适的初始值和学习步长。
一个标准化的方法就是让数据的每一列减去该列的均值,然后除以该列的样本标准差( ):
中心化,只要前面的一步即可:
#标准化和中心化。然后随机梯度下降
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
)在计算梯度时会用到所有观测点,因此算出来的梯度会比较稳定。
全数据梯度下降法的代码例子就不看了。
这两种梯度下降法各自的特点是如此的鲜明,所以必定还会有一种中庸调和的方法,那就是批量随机梯度下降法
(Batch Stochastic Gradient Descent
)。
他在计算梯度时,既不是使用单个观测点,也不是使用所有观测点,而是每次用一小部分观测点,在实际中常用的有16,32~1024个观测点,根据内存和模型规模选取合适的。
批量随机梯度下降法的代码例子也不看了。
学习步长
是一个很重要的参数。
如果太小,算法会收敛的很慢。
如果太大,容易造成算法不收敛,甚至发散。
自变量的标准化,和因变量的中心化,是建立深度学习模型常用的数据预处理方法。
他们的好处,是不仅可以让梯度下降法的数值表现的更加稳定,还有助于我们找到合适的初始值和步长。
在梯度下降法中,学习步长
和batch size
需要事先给定,而不像参数w
一样通过最小化损失函数得到,这类参数在机器学习中叫做超参数
。
接下来是介绍线性分类模型,logistic模型。回归模型
和分类模型
的主要区别就是因变量y的数据类型不一样。
在处理实际问题的时候,根据这个区别,我们就可以选择建立回归模型还是分类模型:
这里有一个数据集,它的内容包含:信用卡余额、每月收入、是否违约。
%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
从上图中可以看到,信用卡余额相对于每月收入来说,对还款违约的影响更大。
一般模型不会直接预测某信用卡用户是否违约,而是预测其违约的概率,表示为P(Default|Balance,Income)
,因为它的值在0和1之间,所以如果直接用类似线性回归模型的方式是不行的,需要对加权和进行变换。即:
函数在统计学文献中称为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
根据这个函数的图形,预测值和x值的关系看的就比较清楚。基本上就是x大于0时,预测值为1的概率大于0.5,而概率大于0.5,可以认为是分类值1。
在logistic模型中,损失函数可以定义为
其中 表示第i个观测点的预测概率值, 表示第i个观测点的因变量的值(0或者1)
观察 等于零或者一的情况,可以做出下的变换
接下来实在是看不下去了,还有求偏导数的主要技巧用到了链式法则,还有其他的太难看了。所以这一小部分跳过。
接下来的内容是深度神经网络。
观察箭头的方向,代表了处理的流程。通过线性回归模型和生物神经元的类比,可以将线性模型称作一个只包含一个神经元的神经网络。
同样的,logistic模型也可以用来进行类比,下图代表的就是预估y等于1的概率的处理过程:
他与线性回归模型的不同点在于: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)
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)
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)
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]
可以看到logistic模型找到的线,有一个右下角的原点预测错误。4个当中1个错误。这个是情理之中,别说机器,让你只画一条决策线,能进行正确的预测划分,你也画不出来。
但是如果可以让你画2条线,那就没什么问题。那么对机器来说,又应该怎么做呢?
- 点赞
- 收藏
- 关注作者
评论(0)