这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战
一 简介
相比于传统的机器学习,深度学习的数据集更加复杂,大多数情况也无法把数据生成数据表来查看,在建模过程中,往往都是设计完模型结构后直接训练模型,只能通过一些指标来观测模型的效果,神经网络内部其实也是“黑箱”,因此我们基本只能控制流程、输入数据、观测结果,不过在学习阶段,尤其在优化算法的过程,我们还是希望能够从更多角度观测数据、观测建模过程,此处我们自己动手,创建一些数据用于实验的原材料,通过一些实验深入了解模型原理,使黑箱更加的‘白化’
二 创建回归类数据集
由于回归类模型的数据,特征和标签都是连续型数值,因为现在我们是先生成数据然后进行建模,因此我们可以生成连续性的回归类模型的数据。此处计划生成两个特征,存在偏差的自变量和因变量存在线性关系的数据集 确定线性方程的系数关系𝑦=2𝑥1−𝑥2+1,我们要生成相应的自变量随机数(符合标准正太分布),并且生成一定的噪声数据,因为现实生活中搜集到的数据往往会因为各种原因存在一定的误差,无法完全描述真实世界的客观规律,按照某种规律生成数据、又人为添加扰动项的创建数据的方法,也是数学领域创建数据常用的一般方法。
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import random
import torch
from torch import nn,optim
import torch.nn.functional as F
from torch.utils .data import Dataset ,TensorDataset,DataLoader
#特征数
num_inputs=2
num_examples=1000
#设置随机种子
torch.manual_seed(300)
#线性方程:𝑦=2𝑥1−𝑥2+1,线性方程系数
w_true=torch.tensor([2.,-1]).reshape(2,1)
b_true=torch.tensor(1.)
#创建特征和标签值
features=torch.randn(num_examples,num_inputs)
labels_true=torch.mm(features,w_true)+b_true
labels=labels_true+torch.randn(size=labels_true.shape)*0.01
2.1 数据探索
features[:5]
labels[:5]
plt.subplot(1,2,1)
plt.scatter(features[:,0],labels,color='r') #第一个特征和标签的关系
plt.subplot(1,2,2)
plt.scatter(features[:,1],labels,color='orange') #第二个特征和标签的关系
此处用scatter代替plt,因为在绘制点图是,大型数据面前,scatter更快
由图看出,两个特征和标签都存在一定的线性关系,并且跟特征的系数绝对值有很大关系。若要增加线性模型的建模难度,可以增加扰动项的数值比例,从而削弱线性关系。
2.2 增加扰动项进行比较
torch.manual_seed(420)
#修改因变量
labels1=labels_true+torch.randn(size=labels_true.shape)*2
#扰动项较小
plt.subplot(221)
plt.scatter(features[:,0],labels,color='r')
plt.subplot(222)
plt.scatter(features[:,1],labels,color='orange');
#扰动性较大
plt.subplot(223)
plt.scatter(features[:,0],labels1,color='blue')
plt.subplot(224)
plt.scatter(features[:,1],labels1,color='green')
通过增加扰动项,线性关系会被削弱。
2.3 生成非线性数据集𝑦=𝑥**2+1
torch.manual_seed(420)
num_inputs=2
num_examples=1000
w_ture=torch.tensor(2.)
b_true=torch.tensor(1.)
features=torch.randn(num_examples,num_inputs)
labels_true=torch.pow(features,2)*w_true+b_true
labels=labels_true+torch.randn(size=labels_true.shape)*0.1
plt.scatter(features,labels,color='red');
2.4 封装成函数
def tensorGenReg(num_examples=1000,w=[2,-1,1],bias=True,delta=0.01,deg=1):
"""
param num_examples:创建数据集的数据量
param w:截距(如果存在)特征系数向量
param bias:是否需要截距
param delta:扰动项系数
param deg:方程次数
return:生成的特征张量和标签张量
"""
if bias==True:
num_inputs=len(w)-1
features_true=torch.randn(num_examples,num_inputs) #特征张量
w_true=torch.tensor(w[:-1]).reshape(-1,1).float() #自变量系数
b_true=torch.tensor(w[-1]).float() #截距
if num_inputs==1: #若输入特征只有一个,不能使用矩阵乘法
labels_true=torch.pow(features_ture,deg)*w_true+b_true
else:
labels_true=torch.mm(torch.pow(features_true,deg),w_true)+b_true
features=torch.cat((features_true,torch.ones(len(features_true),1)),1)
labels=labels_true+torch.randn(size=labels_true.shape)*delta
else:
num_inputs=len(w)
features=torch.randn(num_examples,num_inputs)
w_true=torch.tensor(w).reshape(-1,1).float()
if num_inputs==1:
labels_true=torch.pow(features,deg)*w_true
else:
labels_true=torch.mm(torch.pow(features,deg),w_true)
labels=labels_true+torech.randn(size=labels_true.shape)*delta
return features,labels
2.4.1 线性函数
#测试函数性能,线性
torch.manual_seed(300)
f,l=tensorGenReg(delta=0.01)
print(f)
plt.subplot(223)
plt.scatter(f[:,0],l)
plt.subplot(224)
plt.scatter(f[:,1],l)
2.4.2 二阶函数
#二阶函数
torch.manual_seed(300)
f,l=tensorGenReg(deg=2)
plt.subplot(2,2,3)
plt.scatter(f[:,0],l)
plt.subplot(224)
plt.scatter(f[:,1],l)
三 创建分类数据集
3.1 分类数据集创建
创建一个拥有两个特征的三分类的数据集,每个类别包含500条数据,并且第一个类别的两个特征都服从均值为4、标准差为2的正态分布,第二个类别的两个特征都服从均值为-2、标准差为2的正态分布,第三个类别的两个特征都服从均值为-6、标准差为2的正态分布
torch.manual_seed(300)
num_inputs=2
num_examples=500
#创建自变量
data0=torch.normal(4,2,size=(num_examples,num_inputs))
data1=torch.normal(-2,2,size=(num_examples,num_inputs))
data2=torch.normal(-6,2,size=(num_examples,num_inputs))
#创建标签
label0=torch.zeros(500)
label1=torch.ones(500)
label2=torch.full_like(label1,2)
#合并数据集
features=torch.cat((data0,data1,data2)).float()
labels=torch.cat((label0,label1,label2)).long().reshape(-1,1)
#数据探索
print(features[:5])
print(labels[:5])
plt.scatter(features[:,0],features[:,1],c=labels)
类别彼此交叉情况较少,分类器在此数据集上会有不错表现。若要增加分类器的分类难度,可以将各类的均值压缩,并增加方差,从而增加从二维图像上来看彼此交错的情况。
3.2 增加分类器分类难度
torch.manual_seed(420)
num_inputs=2
num_examples=500
data0=torch.normal(3,4,size=(num_examples,num_inputs))
data1=torch.normal(0,4,size=(num_examples,num_inputs))
data2=torch.normal(-3,4,size=(num_examples,num_inputs))
label0=torch.zeros(500)
label1=torch.ones(500)
label2=torch.full_like(label1,2)
features1=torch.cat((data0,data1,data2)).float()
labels1=torch.cat((label0,label1,label2)).long().reshape(-1,1)
plt.subplot(1,2,1)
plt.scatter(features[:,0],features[:,1],c=labels)
plt.subplot(1,2,2)
plt.scatter(features1[:,0],features[:,1],c=labels1)
3.3 封装成函数
def tensorGenCla(num_examples=500,num_inputs=2,num_class=3,deg_dispersion=[4,2],bias=False):
"""
param num_examples:每个类别的数据数量
param num_inputs:特征数据量
param num_class:标签类别数量
param deg_dispersion:数据分布离散程度,第一个参数表示每个类别数组均值的参考,
第二个参数表示随机数组标准差
param bias:截距
return:生成的特征张量和标签张量
"""
cluster_l=torch.empty(num_examples,1) #各类标签张量形状
mean_=deg_dispersion[0] #各类特征张量的均值
std_=deg_dispersion[1] #各类特征张量的方差
lf=[] #存放各类特征张量列表容器
ll=[] #存放各类标签张量列表容器
k=mean_*(num_class-1)/2 #惩罚因子
for i in range(num_class):
data_temp=torch.normal(i*mean_-k,std_,size=(num_examples,num_inputs))
lf.append(data_temp)
labels_temp=torch.full_like(cluster_l,i)
ll.append(labels_temp)
features=torch.cat(lf).float()
labels=torch.cat(ll).long()
if bias==True:
featues=torch.cat((features,torch.ones(len(features),)),1)
return features,labels
3.4 离散程度比较
torch.manual_seed(300)
f,l=tensorGenCla(deg_dispersion=[6,2]) #离散程度小
f1,l1=tensorGenCla(deg_dispersion=[6,6]) #离散程度大
plt.subplot(1,2,1)
plt.scatter(f[:,0],f[:,1],c=l);
plt.subplot(1,2,2)
plt.scatter(f1[:,0],f1[:,1],c=l1);
四 创建小批量切分函数
在深度学习建模过程中,梯度下降是最常用的求解目标函数的优化方法,针对不同类型、拥有不同函数特性的目标函数,所使用的梯度下降算法也各有不同。目前判断小批量梯度下降(MBGD)是较为“普适”的优化算法,它既有随机梯度下降(SGD)的能够跨越局部最小值点的特性,同时又和批量梯度下降(BGD)一样,拥有相对较快的收敛速度,小批量梯度下降过程中,我们需要对函数进行分批量的切分.
def data_iter(batch_size,features,labels):
"""
param batch_size:每个数据集包含的数据
param features:特征张量
param labels:标签张量
"""
num_examples=len(features)
indices=list(range(num_examples))
random.shuffle(indices)
l=[]
for i in range(0,num_examples,batch_size):
j=torch.tensor(indices[i:min(i+batch_size,num_examples)])
l.append([torch.index_select(features,0,j),torch.index_select(labels,0,j)])
return l
#验证函数功能
torch.manual_seed(420)
featues,labels=tensorGenCla()
l=data_iter(5,features,labels)
l[1]
标签的顺序已经打乱。