文章目录提示:仅仅是学习记录笔记,搬运了学习课程的ppt内容,本意不是抄袭!望大家不要误解!纯属学习记录笔记!!!!!!
- 前言
- 一、机器学习的目标与模型评估方法
- 二、手动实现数据集切分(按照sklearn的切分数据集方法定义函数)
- 三、 Dataset和DataLoader基本使用方法与数据集切分函数
- Dataset中TensorDataset封装x,y函数的创建
- 通过自己做的数据封装函数来建模评估
- 实用函数补充
- 数据封装、切分和加载函数
- 模型训练函数
- 误差平方和MSE计算
- 准确率计算函数
前言
机器学习的总目标是通过测试集训练模型的最佳参数,同时使得该参数在测试集上的泛化误差较小。
一、机器学习的目标与模型评估方法
在统计分析领域,我们会假设现在的数据和未来的数据其实都属于某个存在但不可获得的总体,也就是说,现在和未来的数据都是从某个总体中抽样而来的,都是这个总体的样本。而正式因为这些数据属于同一个总体,因此具备某些相同的规律,而现在挖掘到的数据规律也就在某些程度上可以应用到未来的数据当中去,不过呢,不同抽样的样本之间也会有个体之间的区别,另外模型本身也无法完全捕获规律,而这些就是误差的来源。
虽然样本和总体的概念是统计学概念,但样本和总体的概念所假设的前后数据的“局部规律一致性”,却是所有机器学习建模的基础。试想一下,如果获取到的数据前后描绘的不是一件事情,那么模型训练也就毫无价值(比如拿着A股走势预测的时间序列预测某地区下个季度患病人次)。因此,无论是机器学习所强调的从业务角度出发,要确保前后数据描述的一致性,还是统计分析所强调的样本和总体的概念,都是建模的基础。
在有了假设基础之后,统计分析就会利用一系列的数学方法和数理统计工具去推导总体的基本规律,也就是变量的分布规律和一些统计量的取值,由于这个过程是通过已知的样本去推断未知的总体,因此会有大量的“估计”和“检验”,在确定了总体的基本分布规律之后,才能够进一步使用统计分析模型构建模型(这也就是为什么在数理统计分析领域,构建线性回归模型需要先进行一系列的检验和变换的原因),当然,这些模型都是在总体规律基础之上、根据样本具体的数值进行的建模,我们自然有理由相信这些模型对接下来仍然是从总体中抽样而来的样本还是会具备一定的预测能力,这也就是我们对统计分析模型“信心”的来源。简单来说,就是我们通过样本推断总体的规律,然后结合总体的规律和样本的数值构建模型,由于模型也描绘了总体规律,所以模型对接下来从总体当中抽样而来的数据也会有不错的预测效果。
而对于机器学习来说,并没有借助“样本-总体”的基本理论,而是简单的采用了一种后验的方法来判别模型有效性,前面说到,我们假设前后获取的数据拥有规律一致性,但数据彼此之间又略有不同,为了能够在捕捉规律的同时又能考虑到“略有不同”所带来的误差,机器学习会把当前能获取到的数据划分成训练集(trainSet)和测试集(testSet),在训练集上构建模型,然后带入测试集的数据,观测在测试集上模型预测结果和真实结果之间的差异。这个过程其实就是在模拟获取到真实数据之后模型预测的情况,此前说到,模型能够在未知标签的数据集上进行预测,就是模型的核心价值,此时的测试集就是用于模拟未来的未知标签的数据集。如果模型能够在测试集上有不错的预测效果,我们就“简单粗暴”的认为模型可以在真实的未来获取的未知数据集上有不错的表现。
我们称模型在训练集上误差称为训练误差,在测试集上的误差称为泛化误差,不过毕竟在测试集上进行测试还只是模拟演习,我们采用模型的泛化能力来描述模型在未知数据上的判别能力,当然泛化能力无法准确衡量(未知的数据还未到来,到来的数据都变成了已知数据),我们只能通过模型在训练集和测试集上的表现,判别模型泛化能力,当然,就像此前说的一样,最基本的,我们会通过模型在测试集上的表现来判断模型的泛化能力。
二、手动实现数据集切分(按照sklearn的切分数据集方法定义函数)#手动实现训练集和测试集切分
def data_split(features, labels, rate=0.7):
'''
训练集和测试集切分函数
:param features: 输入的特征张量
:param labels: 输入的标签张量
:param rate: 训练集占所有数据的比例
:return,Xtrain,Xtest,ytrain,ytest:返回特征张量的训练集、测试集以及标签的训练集和测试集
'''
num_examples = len(features)
indices = list(range(num_examples))
random.shuffle(indices)
num_train = int(num_examples * rate)
indices_train = torch.tensor(indices[: num_train])
indices_test = torch.tensor(indices[num_train:])
Xtrain = features[indices_train]
Xtest = features[indices_test]
ytrain = labels[indices_train]
ytest = labels[indices_test]
return Xtrain,Xtest,ytrain,ytest
三、 Dataset和DataLoader基本使用方法与数据集切分函数
Dataset中TensorDataset封装x,y函数的创建
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from sklearn.datasets import load_breast_cancer as LBC
features, labels = tensorGenReg(bias=True)
features = features[:, :-1]
#print(labels)
#print(features)
class LBCDataset(Dataset): #n继承的是Dataset这个父类中的函数
def __init__(self,data): # 创建该类时需要输入sklearn导入的数据集
self.features = data.data # features属性返回数据集特征
self.labels = data.target # labels属性返回数据集标签
self.lens = len(data.data) # lens属性返回数据集大小
def __getitem__(self, index):
# 调用该方法时需要输入index数值,方法最终返回index对应的特征和标签
return self.features[index,:],self.labels[index]
def __len__(self):
# 调用该方法不需要输入额外参数,方法最终返回数据集大小
return self.lens
data = LBC()
LBC_data = LBCDataset(data)
#print(LBC_data.features)
#print(LBC_data.labels)
#确定训练集、测试集大小,此处7:3划分训练集和测试集
num_train = int(LBC_data.lens * 0.7)
num_test = LBC_data.lens - num_train
print(num_train) #398
print(num_test) #171
LBC_train, LBC_test = random_split(LBC_data, [num_train, num_test])
print(LBC_train.dataset)
#<__main__.LBCDataset object at 0x7f9af77c9a60>
#for i in LBC_train:
#print(i)
#break
#我们可以发现每个一个LBC_train样本中都包括特征值和标签值
'''
(array([1.968e+01, 2.168e+01, 1.299e+02, 1.194e+03, 9.797e-02, 1.339e-01,
1.863e-01, 1.103e-01, 2.082e-01, 5.715e-02, 6.226e-01, 2.284e+00,
5.173e+00, 6.766e+01, 4.756e-03, 3.368e-02, 4.345e-02, 1.806e-02,
3.756e-02, 3.288e-03, 2.275e+01, 3.466e+01, 1.576e+02, 1.540e+03,
1.218e-01, 3.458e-01, 4.734e-01, 2.255e-01, 4.045e-01, 7.918e-02]), 0)
'''
通过自己做的数据封装函数来建模评估
#建模及评估过程
#数据准备
features, labels = tensorGenReg()
features = features[:, :-1]
#定义一个封装函数(tensordataset)
class GenData(Dataset): #n继承的是Dataset这个父类中的函数
def __init__(self,features, labels): # 创建该类时需要输入sklearn导入的数据集
self.features = features # features属性返回数据集特征
self.labels = labels # labels属性返回数据集标签
self.lens = len(features) # lens属性返回数据集大小
def __getitem__(self, index):
# 调用该方法时需要输入index数值,方法最终返回index对应的特征和标签
return self.features[index,:],self.labels[index]
def __len__(self):
# 调用该方法不需要输入额外参数,方法最终返回数据集大小
return self.lens
#实例化对象
data = GenData(features, labels)
#切分数据集
mun_train = int(data.lens * 0.7)
num_test = data.lens - num_train
data_train, data_test = random_split(data, [num_train, num_test])
#家在数据
train_loader = DataLoader(data_train, batch_size=10, shuffle=True)
test_loader = DataLoader(data_test, batch_size=10, shuffle=True)
#构建模型
batch_size = 10
lr = 0.03
num_epochs = 3
#1-定义模型
class LR(nn.Module):
def __init__(self, in_put, out_put):
super(LR, self).__init__()
self.linear = nn.Linear(in_put, out_put)
def forward(self, X):
out = self.linear(X)
return out
model = LR(features.shape[1], 1)
#定义损失函数
criterion = nn.MSELoss()
#定义优化方法
optimizer = optim.SGD(model.parameters(), lr=lr)
#模型训练与测试
def fit(net, criterion, optimizer, batchdata, epochs):
for epoch in range(epochs):
for x,y in batchdata:
yhat = net.forward(x)
loss = criterion(yhat, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
fit(net=model,
criterion=criterion,
optimizer=optimizer,
batchdata=train_loader,
epochs=num_epochs)
#print(model)
'''
loss = criterion(yhat, y)
'''
#print(list(model.parameters()))
'''
[Parameter containing:
tensor([[ 1.9988, -1.0004]], requires_grad=True), Parameter containing:
tensor([0.9986], requires_grad=True)]
'''
#计算训练集MSE
MES_train = F.mse_loss(model(data[data_train.indices][0]), data[data_train.indices][1])
#print(data_train)
#
#train_indices = data_train.indices
#print(data[train_indices]) #由于data中包括特征值和标签,索引1是特征,索引0是特征
#然后我们检索出这写训练集的特征,放在模型里训练,对比真是标签值,计算误差平方和
#计算测试集MSE
MSE_test = F.mse_loss(model(data[data_test.indices][0]), data[data_test.indices][1])
print(MES_train, MSE_test)
#tensor(9.9975e-05, grad_fn=) tensor(0.0001, grad_fn=)
实用函数补充
数据封装、切分和加载函数
def split_loader(features, labels, batch_size=10, rate=0.7):
'''
数据封装、切分和加载函数
:param features: 输入的特征
:param labels: 数据集的标签
:param batch_size: 数据集加载时每一小批的数据量
:param rate: 训练集数据占比
:return: 加载好的训练集和测试集
'''
data = GenData(features, labels)
num_train = int(data.lens * rate)
num_test = data.lens - num_train
data_train, data_test = random_split(data, [num_train, num_test]) #讲所有的数据按照具体的数量切分好
train_loader = DataLoader(data_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(data_test, batch_size=batch_size, shuffle=False)
return train_loader, test_loader
#测试函数
#设置随机种子
torch.manual_seed(420)
features, labels = tensorGenReg()
features = features[:, :-1]
#进行数据加载
train_loader, test_loader = split_loader(features, labels)
#print(test_loader)
#print(train_loader)
print(len(list(test_loader))) #30
print(len(list(train_loader)) #70
模型训练函数
def fit(net, criterion, optimizer, batchdata, epochs=3, cla=False):
'''模型训练函数
:param net: 待训练的网络
:param criterion: 损失函数
:param optimizer: 优化算法
:param batchdata: 训练数据集
:param epoch: 遍历数据的次数
:param cla: 是否是分类问题
'''
for epoch in range(epochs):
for X,y in batchdata:
if cla == True:
y = y.flatten().long()
#将标签转化成整数
yhat = net.forward()
loss = criterion(yhat, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
误差平方和MSE计算
def mse_cal(data_loader, net):
'''mse误差平方和计算函数
:param data_loader: 加载好的数据
:param net: 模型
:return: 根据输入的数据,输出其MSE计算结果
'''
data = data_loader.dataset #还原Dataset类
X = data[:][0] #还原数据的特征
y = data[:][1] #还原数据的标签
yhat = net(X)
return F.mse_loss(yhat, y)
#设置随机种子
torch.manual_seed(420)
features, labels = tensorGenReg()
features = features[:, :-1]
#进行数据加载
train_loader, test_loader = split_loader(features, labels)
print(train_loader)
#
print(train_loader.dataset[:]) #将数据还原
print(train_loader.dataset[:][0]) #将数据的特征值取出
print(train_loader.dataset[:][1]) #将数据的标签值取出
准确率计算函数
def accuracy_cal(data_loader, net):
'''准确率计算
:param data_loader: 加载好的数据
:param net: 模型
:return: 根据输入的数据,输出其准确率计算结果
'''
data = data_loader.dataset #还原数据
x = data[:][0]
y = data[:][1]
zhat = net(x) #默认是分类问题,其输出结果是未经过softmax转化的结果
soft_z = F.softmax(zhat, dim=1)
acc_bool = torch.argmax(soft_z).flatten() == y.flatten
acc = torch.mean(acc_bool.float()) #最好使用torch自带的计算函数,因为这种torch的算力更强
return acc
测试准确率模型是否可以正常运行
# 实例化模型和
softmax_model = softmaxR()
# 定义损失函数
criterion = nn.CrossEntropyLoss()
# 定义优化算法
optimizer = optim.SGD(softmax_model.parameters(), lr=0.03)
# 执行模型训练
fit(net = softmax_model,
criterion = criterion,
optimizer = optimizer,
batchdata = train_loader,
epochs = 3,
cla=True)
print(accuracy_cal(train_loader, softmax_model))
print(accuracy_cal(test_loader, softmax_model))



