IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 李宏毅2021春机器学习HW1——记录与拓展 -> 正文阅读

[人工智能]李宏毅2021春机器学习HW1——记录与拓展

目录

前言

一、作业介绍

二、搭建模型

1.思路

2.程序编写

三、 运行的结果

前言

如题,本文是针对李宏毅老师2021春机器学习课程的作业1,所做的记录与拓展。

一、作业介绍

作业1是有关于美国2020年某一时间段内新冠疫情确诊人数的预测,并且提供了两份数据文件(covid.train.csv和covid.test.csv)。

①covid.train.csv文件

文件中包含了94列的数据,其中前40列数据表示美国的州,其后的每18列作为一天内产生的数据。这18列中,前17列是被调查者的实际情况,第18列是测试为阳性的比例。

②covid.test.csv文件

文件形式与前面的训练数据相同,不同的是第三天的第18列(测试为阳性的比例)需要通过模型来预测,这也是本次作业的目的。

二、搭建模型

1.思路

编程的思路可以分成三部分:

①数据的处理

②模型的搭建

③目标的预测

④结果存储与可视化

2.程序编写

(1)数据的处理

这一部分比较繁琐,需要先将数据处理好以后,才能够顺利的让模型跑起来。

· 所涉及的关键知识:Dataset, DataLoader。

? ? ? ? Dataset, DataLoader两者是相辅相成的。前者用于处理数据,后者用于读取数据。

? ? ? ? · 关于Dataset类:

????????????????在使用这个作为父类时,子类需要重写__getitem__(self,item)函数,这个函数可以获取数据中指定元素,相当于self[key],即允许类对象可以有索引操作。DataLoader返回数据就是根据这个函数来返回的。

????????· 关于DataLoader类:

????????????????这个类主要是根据需求设置参数。其中,shuffle决定是否打乱样本顺序;drop_last决定是否丢弃最后一批不能被batch_size整除的剩余样本;num_workers决定用多少个进程来加载数据,默认为0,即只用主进程;pin_memory决定是否将数据载入CUDA的内存当中。

【具体的程序如下面的代码块所示,代码后面有相应的注释】

# 这一模块需要引入的库:
import csv
import numpy 
import tensor
from tensor.utils.data import Dataset, DataLoader

class Covid19dataset(Dataset):
    def __init__(self, path, mode='train'):
        super().__init__()
        self.mode = mode

        # 读取数据
        with open(path) as file:
            data_csv = list(csv.reader(file))   # 将csv文件中获取的数据转换为列表类型
            data = np.array(data_csv[1:])[:, 1:].astype(float)  # 获取文件中的【数值数据】

        if mode == 'test':  # 由于训练集、验证集与测试集的数据有所不同(最后一列数据),在此分情况运行
            data = data[:, 0:93]    # 测试集中,由于最后一行是得预测的数据,故只有93列
            self.data = torch.FloatTensor(data)     # 将numpy类型数据转换为tensor类型
        else:
            target = data[:, -1]    # 训练集和验证集中用于对比结果的“目标”
            data = data[:, 0:93]
            train_index = []
            dev_index = []
            for i in range(data.shape[0]):     # 这个循环用于将covid.train.csv文件中的数据分为训练集和验证集
                if i % 10 != 0:                # 取序号为整十数的样本作为验证集
                    train_index.append(i)
                else:
                    dev_index.append(i)
            if mode == 'train':     # 训练集的数据
                self.target = torch.FloatTensor(target[train_index])
                self.data = torch.FloatTensor(data[train_index, 0:93])
            else:       # 测试集的数据
                self.target = torch.FloatTensor(target[dev_index])
                self.data = torch.FloatTensor(data[dev_index, 0:93])

        # 此处是对数据进行标准化处理,可以将不同量纲的不同特征,变为同一个数量级,使得损失函数更加平滑
        # 标准化的优点:①提升模型的精度   ②提升收敛速度
        # 采用均值标准化: (第i维数据 - 第i维数据的平均值)/(第i维数据的标准差)
        self.data[:, 40:] = (self.data[:, 40:] - self.data[:, 40:].mean(dim=0)) / self.data[:, 40:].std(dim=0)

        self.dim = self.data.shape[1]   # 获取数据的列数

    def __getitem__(self, item):        # 【注】这是Dataset必须重写的类函数,意在按索引返回数据
        if self.mode == 'train' or self.mode == 'dev':  # 训练集和验证集包含特征和目标数据
            return self.data[item], self.target[item]
        else:
            return self.data[item]      # 测试集仅含有特征数据

    def __len__(self):                  # 【注】返回数据的行数
        return len(self.data)


def prep_dataloader(path, mode, batch_size, n_jobs=0):
    dataset = Covid19dataset(path, mode)    # 定义一个Dataset类
    dataloader = DataLoader(dataset, batch_size,
                            shuffle=(mode == 'train'),  # 【是否打乱数据后再读取】
                            drop_last=False,            # 【False表示不丢弃不能被batch_size整除的部分】
                            num_workers=n_jobs,         # 【采用多少个进程读取数据】
                            pin_memory=False)           # 【是否将数据载入CUDA的内存当中】
    print(mode, 'data done!')
    return dataloader

(2)模型的搭建

思路:

①先编写好模型的结构

②训练模型,同时每一个epoch结束后,用验证集计算模型的Loss,存储表现好的模型

# 这一模块涉及到的库
import os
from torhc import nn, optim

# 这部分可以直接到pytorch的官方文档中查看对应类或函数的使用方法
# 设置模型的结构
class Mymodel(nn.Module):       
    def __init__(self, input_dim):
        super(Mymodel, self).__init__()
        self.net = nn.Sequential(           # 设置好模型的结构,可在forward函数中直接按顺序运行
            nn.Linear(input_dim, 100),
            nn.ReLU(),
            nn.Linear(100, 1)
        )

        self.criterion = nn.MSELoss(reduction='mean')   # 计算Loss

    def forward(self, x):
        return self.net(x).squeeze(1)       # 对数据的维度进行压缩,方便预测值与实际值的对比

    def cal_loss(self, pred, target):
        return self.criterion(pred, target)     # 计算Loss

# 训练模型
def train(model, train_data, dev_data):    
    max_epoch = 3000    # 至多训练次数
    epoch = 1
    optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)   # 初始化梯度下降法
    train_loss = []     # 存储训练集的Loss
    dev_loss = []       # 存储测试集的Loss
    min_mse = 1000
    break_flag = 0
    while epoch < max_epoch:
        model.train()               # 设置模式
        for x, y in train_data:     # x,y 每次包含一个batch_size的样本
            optimizer.zero_grad()   # 每次必须先将梯度清零
            pred = model(x)
            loss = model.cal_loss(pred, y)  # 计算Loss
            train_loss.append(loss.detach())
            loss.backward()         # 计算梯度
            optimizer.step()        # 模型的参数更新

        dev_mse = dev(model, dev_data)
        if dev_mse < min_mse:       # 如果测试验证集的Loss比上一次小,则存储当前模型
            min_mse = dev_mse
            print('Saving model (epoch = {:4d}, loss = {:.4f})'
                  .format(epoch + 1, min_mse))

            # 存储当前最好的模型,此处需要导入os库,创建相应的目录
            torch.save(model.state_dict(), 'my_models/mymodel.pth')

            break_flag = 0
        else:
            break_flag += 1

        dev_loss.append(dev_mse.detach())

        if break_flag > 200:    # 如果连续200个周期,Loss都没有下降,则结束训练
            break

        epoch += 1
    return train_loss, dev_loss

# 测试模型
def dev(model, dev_data):        
    model.eval()            # 设置模式
    total_loss = []

    for x, y in dev_data:       # 得到当前模型下验证集的Loss
        pred = model(x)
        dev_loss = model.cal_loss(pred, y)
        total_loss.append(dev_loss)

    return sum(total_loss) / len(total_loss)    # 取Loss的平均数

(3)目标的预测


# 用Loss最低的模型进行预测
def test(model, test_data):        
    model.eval()            # 设置模式
    preds = []
    for x in test_data:     # 计算获得【预测值】
        pred = model(x)
        preds.append(pred.detach().cpu())    # detach会分离出一个新的tensor,这个tensor不能够求导
    preds = torch.cat(preds, dim=0).numpy()
    return preds

(4)结果存储与可视化

# 绘制学习曲线
def plot_learning_curve(train_loss, dev_loss, title=''):
    total_steps = len(train_loss)
    x_1 = range(total_steps)
    x_2 = x_1[::len(train_loss) // len(dev_loss)]
    plt.figure(1, figsize=(6, 4))
    plt.plot(x_1, train_loss, c='tab:red', label='train')
    plt.plot(x_2, dev_loss, c='tab:cyan', label='dev')
    plt.ylim(0.0, 5.)       # 【设置y的上下限】
    plt.xlabel('Training steps')
    plt.ylabel('MSE loss')
    plt.title('Learning curve of {}'.format(title))
    plt.legend()        # 【放一个图例说明】
    plt.show()

# 绘制验证集的预测值与实际值
def plot_pred(dv_set, model, device, lim=35., preds=None, targets=None):
    if preds is None or targets is None:
        model.eval()
        preds, targets = [], []
        for x, y in dv_set:
            x, y = x.to(device), y.to(device)
            with torch.no_grad():
                pred = model(x)
                preds.append(pred.detach().cpu())
                targets.append(y.detach().cpu())
        preds = torch.cat(preds, dim=0).numpy()
        targets = torch.cat(targets, dim=0).numpy()
    plt.figure(2, figsize=(5, 5))
    plt.scatter(targets, preds, c='r', alpha=0.5)
    plt.plot([-0.2, lim], [-0.2, lim], c='b')
    print(targets[-10:-1])
    plt.xlim(-0.2, lim)
    plt.ylim(-0.2, lim)
    plt.xlabel('ground truth value')
    plt.ylabel('predicted value')
    plt.title('Ground Truth v.s. Prediction')
    plt.show()

# 保存测试集的预测结果
def save_pred(preds, file):
    print('Saving results to {}'.format(file))
    with open(file, 'w') as fp:
        writer = csv.writer(fp)
        writer.writerow(['id', 'tested_positive'])
        for i, p in enumerate(preds):   # enumerate() 函数用于将一个可遍历的数据对象组合为一个索引序列,同时列出数据和数据下标
            writer.writerow([i, p])

?(5)程序运行流程

# 设置存储模型的目录
os.makedirs('my_models', exist_ok=True)

# 加载数据
train_data = prep_dataloader('covid.train.csv', 'train', batch_size=135)
dev_data = prep_dataloader('covid.train.csv', 'dev', batch_size=135)
test_data = prep_dataloader('covid.test.csv', 'test', batch_size=135)

# 设置模型与训练
mymodel = Mymodel(train_data.dataset.dim)
train_loss, dev_loss = train(mymodel, train_data, dev_data)
plot_learning_curve(train_loss, dev_loss, title='deep model')
del mymodel

# 加载最好的模型进行预测
model = Mymodel(train_data.dataset.dim)
ckpt = torch.load('my_models/mymodel.pth', map_location='cpu')  # 加载最好的模型
model.load_state_dict(ckpt)
plot_pred(dev_data, model, 'cpu')
preds = test(model, test_data)

# 储存预测结果
save_pred(preds, 'mypred.csv')
print('All Done!')

三、 运行的结果

在此模型中,batch_size=135, lr=0.001,momentum=0.9,采用了均值标准化。基本的要求能够满足,但是模型仍然有很多可以优化的地方。

初学机器学习的小白,如有不妥之处请见谅,欢迎批评指正!

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:30:37  更:2021-08-01 14:31:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/22 9:48:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码