HW 4

Download

!gdown --id '1ksbRUG0S646Y-mhN0t5RZSSlE9BLlFKh' --output Dataset.zip #这是我云盘的链接,能跑得动就是了
!unzip Dataset.zip

dataset

选取的是Voxceleb.1数据集,随机挑选了600个发言的来组成

dataset的构成

  • Args:

    • data_dir: The path to the data directory.
    • metadata_path: The path to the metadata.
    • segment_len: The length of audio segment for training.
  • The architecture of data directory
    • data directory
      |---- metadata.json
      |---- testdata.json
      |---- mapping.json
      |---- uttr-{random string}.pt
  • The information in metadata
    • “n_mels”: The dimention of mel-spectrogram. #梅尔频谱,通过spectrogram和若干的梅尔滤波器得到
    • “speakers”: A dictionary.
      • Key: speaker ids.
      • value: “feature_path” and “mel_len”
import os
import json
import torch
import random
from pathlib import Path
from torch.utils.data import Dataset
from torch.nn.utils.rnn import pad_sequenceclass myDataset(Dataset):def __init__(self, data_dir, segment_len=128): #初始化self.data_dir = data_dirself.segment_len = segment_len# Load the mapping from speaker neme to their corresponding id. mapping_path = Path(data_dir) / "mapping.json"mapping = json.load(mapping_path.open())self.speaker2id = mapping["speaker2id"]# Load metadata of training data.metadata_path = Path(data_dir) / "metadata.json"metadata = json.load(open(metadata_path))["speakers"]# Get the total number of speaker.self.speaker_num = len(metadata.keys())self.data = []for speaker in metadata.keys():for utterances in metadata[speaker]:self.data.append([utterances["feature_path"], self.speaker2id[speaker]])def __len__(self):return len(self.data)def __getitem__(self, index):feat_path, speaker = self.data[index]# Load preprocessed mel-spectrogram.mel = torch.load(os.path.join(self.data_dir, feat_path))# Segmemt mel-spectrogram into "segment_len" frames.if len(mel) > self.segment_len:# Randomly get the starting point of the segment.start = random.randint(0, len(mel) - self.segment_len) #随机选个起始点# Get a segment with "segment_len" frames.mel = torch.FloatTensor(mel[start:start+self.segment_len])else:mel = torch.FloatTensor(mel)# Turn the speaker id into long for computing loss later.speaker = torch.FloatTensor([speaker]).long()return mel, speakerdef get_speaker_number(self):return self.speaker_num

Dataloader

import torch
from torch.utils.data import DataLoader, random_split
from torch.nn.utils.rnn import pad_sequencedef collate_batch(batch):# Process features within a batch."""Collate a batch of data."""mel, speaker = zip(*batch)# Because we train the model batch by batch, we need to pad the features in the same batch to make their lengths the same.mel = pad_sequence(mel, batch_first=True, padding_value=-20)    # pad log 10^(-20) which is very small value. pad_sequence将其拉伸到一样的长度,这个batch_first是将batch放置在第一维# mel: (batch size, length, 40)return mel, torch.FloatTensor(speaker).long()def get_dataloader(data_dir, batch_size, n_workers):"""Generate dataloader"""dataset = myDataset(data_dir)speaker_num = dataset.get_speaker_number()# Split dataset into training dataset and validation datasettrainlen = int(0.9 * len(dataset)) #分成91开lengths = [trainlen, len(dataset) - trainlen]trainset, validset = random_split(dataset, lengths) #随机函数!下次用用试试train_loader = DataLoader(trainset,batch_size=batch_size,shuffle=True,drop_last=True, #如果除完有剩下的就用剩下的num_workers=n_workers,pin_memory=True,collate_fn=collate_batch,  #自定义的分配函数,后续会进行描述)valid_loader = DataLoader(validset,batch_size=batch_size,num_workers=n_workers,drop_last=True,pin_memory=True,collate_fn=collate_batch,)return train_loader, valid_loader, speaker_num

Model

  • TransformerEncoderLayer:

    • Base transformer encoder layer in Attention Is Al l You Need
    • Parameters:
      • d_model: the number of expected features of the input (required).
      • nhead: the number of heads of the multiheadattention models (required).
      • dim_feedforward: the dimension of the feedforward network model (default=2048).
      • dropout: the dropout value (default=0.1). #防止过拟合,提升模型泛化能力
      • activation: the activation function of intermediate layer, relu or gelu (default=relu).
  • TransformerEncoder:
    • TransformerEncoder is a stack of N transformer encoder layers
    • Parameters:
      • encoder_layer: an instance of the TransformerEncoderLayer() class (required).
      • num_layers: the number of sub-encoder-layers in the encoder (required).
      • norm: the layer normalization component (optional).
import torch
import torch.nn as nn
import torch.nn.functional as Fclass Classifier(nn.Module):def __init__(self, d_model=80, n_spks=600, dropout=0.1):super().__init__()# Project the dimension of features from that of input into d_model.self.prenet = nn.Linear(40, d_model)# TODO:#   Change Transformer to Conformer.#   https://arxiv.org/abs/2005.08100# 我代码层实现不了啊!泪目self.encoder_layer = nn.TransformerEncoderLayer(d_model=d_model, dim_feedforward=256, nhead=2)# self.encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=2)# Project the the dimension of features from d_model into speaker nums.self.pred_layer = nn.Sequential(nn.Linear(d_model, d_model),nn.ReLU(), #我想换成Swish的,但是我代码层实现不了nn.Linear(d_model, n_spks),)def forward(self, mels):"""args:mels: (batch size, length, 40)return:out: (batch size, n_spks)"""# out: (batch size, length, d_model)out = self.prenet(mels)# out: (length, batch size, d_model)out = out.permute(1, 0, 2) #重新塑形# The encoder layer expect features in the shape of (length, batch size, d_model).out = self.encoder_layer(out)# out: (batch size, length, d_model)out = out.transpose(0, 1)# mean poolingstats = out.mean(dim=1)# out: (batch, n_spks)out = self.pred_layer(stats)return out

Learning rate schedule

import mathimport torch
from torch.optim import Optimizer
from torch.optim.lr_scheduler import LambdaLRdef get_cosine_schedule_with_warmup(optimizer: Optimizer,num_warmup_steps: int,num_training_steps: int,num_cycles: float = 0.5,last_epoch: int = -1, #如果有剩余的就一起用了
):"""Create a schedule with a learning rate that decreases following the values of the cosine function between theinitial lr set in the optimizer to 0, after a warmup period during which it increases linearly between 0 and theinitial lr set in the optimizer.Args:optimizer (:class:`~torch.optim.Optimizer`):The optimizer for which to schedule the learning rate.num_warmup_steps (:obj:`int`):The number of steps for the warmup phase.num_training_steps (:obj:`int`):The total number of training steps.num_cycles (:obj:`float`, `optional`, defaults to 0.5):The number of waves in the cosine schedule (the defaults is to just decrease from the max value to 0following a half-cosine).last_epoch (:obj:`int`, `optional`, defaults to -1):The index of the last epoch when resuming training.Return::obj:`torch.optim.lr_scheduler.LambdaLR` with the appropriate schedule."""def lr_lambda(current_step):# Warmupif current_step < num_warmup_steps:return float(current_step) / float(max(1, num_warmup_steps))*0.8#自己加的,我不会改啊# decadenceprogress = float(current_step - num_warmup_steps) / float(max(1, num_training_steps - num_warmup_steps))return max(0.0, 0.5 * (1.0 + math.cos(math.pi * float(num_cycles) * 2.0 * progress)))return LambdaLR(optimizer, lr_lambda, last_epoch)

Model Function

import torchdef model_fn(batch, model, criterion, device):"""Forward a batch through the model."""mels, labels = batchmels = mels.to(device)labels = labels.to(device)outs = model(mels)loss = criterion(outs, labels)# Get the speaker id with highest probability.preds = outs.argmax(1)# Compute accuracy.accuracy = torch.mean((preds == labels).float())return loss, accuracy

这段就是常见的基础定义,不多进行赘述

Validate(验证)

from tqdm import tqdm
import torchdef valid(dataloader, model, criterion, device): """Validate on validation set."""model.eval()running_loss = 0.0running_accuracy = 0.0pbar = tqdm(total=len(dataloader.dataset), ncols=0, desc="Valid", unit=" uttr")#进度条文件for i, batch in enumerate(dataloader):with torch.no_grad():loss, accuracy = model_fn(batch, model, criterion, device)running_loss += loss.item()running_accuracy += accuracy.item()pbar.update(dataloader.batch_size)pbar.set_postfix(loss=f"{running_loss / (i+1):.2f}",accuracy=f"{running_accuracy / (i+1):.2f}",) #写在进度条旁边的字段pbar.close()model.train()return running_accuracy / len(dataloader)

Main function

from tqdm import tqdmimport torch
import torch.nn as nn
from torch.optim import AdamW
from torch.utils.data import DataLoader, random_splitdef parse_args():"""arguments"""config = {"data_dir": "./Dataset","save_path": "model.ckpt","batch_size": 128,"n_workers": 8,"valid_steps": 2000,"warmup_steps": 1000,"save_steps": 10000,"total_steps": 70000,}return configdef main(data_dir,save_path,batch_size,n_workers,valid_steps,warmup_steps,total_steps,save_steps,
):"""Main function."""device = torch.device("cuda" if torch.cuda.is_available() else "cpu")print(f"[Info]: Use {device} now!")train_loader, valid_loader, speaker_num = get_dataloader(data_dir, batch_size, n_workers)train_iterator = iter(train_loader)print(f"[Info]: Finish loading data!",flush = True)model = Classifier(n_spks=speaker_num).to(device)criterion = nn.CrossEntropyLoss() #交叉熵计算optimizer = AdamW(model.parameters(), lr=1e-3) #Adam衰减scheduler = get_cosine_schedule_with_warmup(optimizer, warmup_steps, total_steps)print(f"[Info]: Finish creating model!",flush = True)best_accuracy = -1.0best_state_dict = Nonepbar = tqdm(total=valid_steps, ncols=0, desc="Train", unit=" step")for step in range(total_steps):# Get datatry:batch = next(train_iterator)except StopIteration:train_iterator = iter(train_loader)batch = next(train_iterator)loss, accuracy = model_fn(batch, model, criterion, device)batch_loss = loss.item()batch_accuracy = accuracy.item()# Updata modelloss.backward()optimizer.step()scheduler.step()optimizer.zero_grad()# Logpbar.update()pbar.set_postfix(loss=f"{batch_loss:.2f}",accuracy=f"{batch_accuracy:.2f}",step=step + 1,)# Do validationif (step + 1) % valid_steps == 0:pbar.close()valid_accuracy = valid(valid_loader, model, criterion, device)# keep the best modelif valid_accuracy > best_accuracy:best_accuracy = valid_accuracybest_state_dict = model.state_dict()pbar = tqdm(total=valid_steps, ncols=0, desc="Train", unit=" step")# Save the best model so far.if (step + 1) % save_steps == 0 and best_state_dict is not None:torch.save(best_state_dict, save_path)pbar.write(f"Step {step + 1}, best model saved. (accuracy={best_accuracy:.4f})")pbar.close()#日常配置了,不多赘述
if __name__ == "__main__":main(**parse_args())

Dataset of Inference

一个后续主函数要用到的数据集,用于定义inference_collate_batch来进行batch的分配

import os
import json
import torch
from pathlib import Path
from torch.utils.data import Datasetclass InferenceDataset(Dataset):def __init__(self, data_dir):testdata_path = Path(data_dir) / "testdata.json"metadata = json.load(testdata_path.open())self.data_dir = data_dirself.data = metadata["utterances"]def __len__(self):return len(self.data)def __getitem__(self, index):utterance = self.data[index]feat_path = utterance["feature_path"]mel = torch.load(os.path.join(self.data_dir, feat_path))return feat_path, meldef inference_collate_batch(batch):"""Collate a batch of data."""feat_paths, mels = zip(*batch)return feat_paths, torch.stack(mels)

Main function of Inference

定义与写文件

import json
import csv
from pathlib import Path
from tqdm.notebook import tqdmimport torch
from torch.utils.data import DataLoaderdef parse_args():"""arguments"""config = {"data_dir": "./Dataset","model_path": "./model.ckpt","output_path": "./output.csv",}return configdef main(data_dir,model_path,output_path,
):"""Main function."""device = torch.device("cuda" if torch.cuda.is_available() else "cpu")print(f"[Info]: Use {device} now!")mapping_path = Path(data_dir) / "mapping.json"mapping = json.load(mapping_path.open())dataset = InferenceDataset(data_dir)dataloader = DataLoader(dataset,batch_size=1,shuffle=False,drop_last=False,num_workers=8,collate_fn=inference_collate_batch,)print(f"[Info]: Finish loading data!",flush = True)speaker_num = len(mapping["id2speaker"])model = Classifier(n_spks=speaker_num).to(device)model.load_state_dict(torch.load(model_path))model.eval()print(f"[Info]: Finish creating model!",flush = True)results = [["Id", "Category"]]for feat_paths, mels in tqdm(dataloader):with torch.no_grad():mels = mels.to(device)outs = model(mels)preds = outs.argmax(1).cpu().numpy()for feat_path, pred in zip(feat_paths, preds):results.append([feat_path, mapping["id2speaker"][str(pred)]])with open(output_path, 'w', newline='') as csvfile:writer = csv.writer(csvfile)writer.writerows(results)if __name__ == "__main__":main(**parse_args())

总结

最后跑出来好像是刚刚到达baseline,连medium的脚都冇碰到(泪目),太菜了,只能接着学下去了…这个看不懂还倒腾了好几天(不过这几天回家也荒废了不少时间),这个作业也暂时算是结束了,看看后面学完以后能不能来优化一哈。

李宏毅机器学习HW4 代码相关推荐

  1. 视频+笔记+能够跑通的代码,《李宏毅机器学习完整笔记》发布!

    点击我爱计算机视觉标星,更快获取CVML新技术 [导读]关于机器学习的学习资料从经典书籍.免费公开课到开源项目应有尽有,可谓是太丰富啦,给学习者提供了极大的便利.但网上比比皆是的学习资料大部分都是英文 ...

  2. 李宏毅机器学习-代码实践

    1. 学习目的 使用Logistics Regression进行数据分类. 2. 学习要求 学习LR学习算法的核心代码 写出详细的注释说明 3. 代码实践 (1)创建数据 def generate_d ...

  3. 李宏毅机器学习-explainable machine learning(机器学习的可解释性)及代码

    目录 为什么需要机器学习的可解释性? Interpretable VS Powerful 什么叫做好的 Explanation explainable ML的分类 Local Explanation( ...

  4. 2022李宏毅作业hw4 - 挫败感十足的一次作业。

    系列文章: 2022李宏毅作业hw1-新冠阳性人员数量预测._亮子李的博客-CSDN博客_李宏毅hw1 hw-2 李宏毅2022年作业2 phoneme识别 单strong-hmm详细解释._亮子李的 ...

  5. 《李宏毅机器学习特训营》免费开放!直播教学!

    AlphaGo战胜"石神"李世石,人工智能开始闯进大众的视野,机器学习成为同学入门人工智能领域的学习首选. 提起机器学习,就不能不说一位人物,他就是台湾大学李宏毅教授.李宏毅老师说 ...

  6. 喜大普奔:Datawhale开源项目《李宏毅机器学习完整笔记》发布了!

    开源地址 https://github.com/datawhalechina/leeml-notes [导读]关于机器学习的学习资料从经典书籍.免费公开课到开源项目应有尽有,可谓是太丰富啦,给学习者提 ...

  7. 李宏毅机器学习完整笔记发布,AI界「最热视频博主」中文课程笔记全开源

    点上方"小詹学Python",选择"置顶公众号"第一时间获取干货分享!本文转自:Datawhale 提起李宏毅老师,熟悉机器学习的读者朋友一定不会陌生.很多人选 ...

  8. python线性回归预测pm2.5_线性回归预测PM2.5----台大李宏毅机器学习作业1(HW1)

    一.作业说明 给定训练集train.csv,要求根据前9个小时的空气监测情况预测第10个小时的PM2.5含量. 训练集介绍: (1).CSV文件,包含台湾丰原地区240天的气象观测资料(取每个月前20 ...

  9. 李宏毅机器学习作业6-使用GAN生成动漫人物脸

    理论部分参考:​李宏毅机器学习--对抗生成网络(GAN)_iwill323的博客-CSDN博客 目录 任务和数据集 评价方法 FID AFD (Anime face detection) rate 代 ...

最新文章

  1. 在React Hook里使用history.push跳转
  2. HTML5学习笔记简明版(10):过时的元素和属性
  3. 上帝给你关闭一道门,就会为你打开一扇窗,反推。
  4. 实战SSM_O2O商铺_42【前端展示】店铺列表页面View层的实现
  5. mysql java safe model_被 MySQL sql_mode 深深伤害( 中 )
  6. 【软考】《希赛教育·软件设计师考前冲刺与考点分析》计算机硬件基础知识——学习笔记
  7. 联想声卡驱动linux版本,Linux声卡驱动
  8. 微信小程序---选项卡
  9. 苹果App Store商店中国区如何改为美国区
  10. 行业顶级NoSQL成员坐阵,NoSQL数据库专场重点解析!
  11. 网吧玩吃鸡提示服务器维护,绝地求生游戏更新维护给网吧带来的影响
  12. 微信Android热补丁实践演进之路
  13. 信息熵与老鼠试药、称球问题
  14. Linux与Windows的区别与比较,及Linux基本命令
  15. iPhone X适配之启动图适配教程
  16. 教你用C++做一个简单的用户名以及密码注册系统
  17. 中国父母最大的失职,就是没对孩子进行金钱教育
  18. flask sqlalchemy 统计 查询
  19. 【最具价值CTO评选秀】出门问问CTO雷欣:从技术极客到核心管理的秘密
  20. 多多情报通:拼多多蓝海词是什么意思?拼多多蓝海词怎么找?

热门文章

  1. 【Adobe】解决 Indesign 因 plugplugowl.dll 出现闪退问题
  2. 浪潮服务器进u盘硬盘没有初始化,出现驱动器 H 中的磁盘未被初始化.想现在初始化吗?要怎么修护U盘啊...
  3. 设备软件控制平台会是什么样子?
  4. 视觉SLAM十四讲笔记-7-2
  5. 网维大师那个版本带虚拟盘服务器,网维大师游戏虚拟盘服务端
  6. 计算机犯困,总是坐在电脑前就犯困是什么原因呢
  7. 软件测试——性能测试
  8. LAMMPS实操系列(二): 大量FCC-CoCrCuFeNi高熵合金建模与最稳定结构筛选
  9. ubuntu 更改桌面路径
  10. MD5、SHA1、CRC32值是干什么的?