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

系列文章:

        2022李宏毅作业hw1—新冠阳性人员数量预测。_亮子李的博客-CSDN博客_李宏毅hw1

         hw-2 李宏毅2022年作业2 phoneme识别 单strong-hmm详细解释。_亮子李的博客-CSDN博客_李宏毅hw2

     2021李宏毅作业hw3 --食物分类。对比出来的80准确率。_亮子李的博客-CSDN博客_李宏毅hw3

地址:

git地址:

https://github.com/xiaolilaoli/lihongyi2022homework/tree/main/hw4_speaker

数据和比赛地址: 

ML2022Spring-hw4 | Kaggle

前言:

          作业4主要难点应该在于视频里模块的应用。因为都是一些陌生的模块,所以写起来会没那么容易。做了作业才发现transformer的模块的真的有很多很多。

        但是我觉得还有更难的地方,就在于hw4的验证集和测试集分布有一些差别。这样导致我一时间非常蒙蔽然后不知道怎么办了。 试问你一直以来坚持的目标,你达到之后才知道那是个错误切虚幻的,你的心会作何感想? 我现在就是这种感觉。

最后的成绩是这个  没有达到strong,比较难受。因为我电脑跑这个作业实在是太慢了 不像以前的作业,可以让我慢慢迭代。尝试很多的结构和参数,这个作业如果大一点 一个epo要接近11分钟。。。然后每次要两百个epo。。。到这里不禁感叹 资源才是王道啊 。。。

 

一个BUG:

        一开始的时候, 我的验证集准确率高达百分之89。我心里高高兴兴,快快乐乐的,去kaggle提交了答案。然后,下面就是我不信邪的结果。

是的,即使我不信邪的提交了无数次,但发现自己仍然是 毫无变化而且准确率极低。我审查了每一步代码试图找到出错的原因。还是没找到,最后不得不求助朋友,让他把他的代码发给我看。经过一步一步审查,终于发现了错误的地方在哪。 错误的原因就在于我自作主张的把测试集的长度模仿训练集和验证集做了裁剪。 在训练的时候,对于长度超过seg_len(我当时是128)的样本,都会进行裁剪, 验证的时候同样。但是在官方代码里,并没有对测试集数据进行裁剪,所以就导致测试集的batch只能为1(因为样本长度不同). 我一看,这怎么可以,果断三下五除二把测试集也裁剪了。最后就导致测试集上的效果极差。 当我把测试集原样送进模型,果然正确率得到了很大的提升。 但是还是比验证集低上很多。 其实这就已经说明训练集和测试集的分布是差了很多很多的。

        为什么我验证集上裁剪, 正确率依然可以达到90.而在提交的测试集上裁剪,准确率只有60呢?理论上来说,网络应该关注的是发言人的声色。那么发言人说话的长度应该对结果没有什么影响才对。但是实验强烈的反驳了这一点。长度,就是有关系,而且关系挺大的。这个现象的深层原因我也不知道为什么,如果有大佬知道,评论一下呗。

正文:

 1 数据部分

                

数据部分 ,可以看下 官方的视频 和 官方的代码。这次的任务,是根据一段音频来预测这段话是谁说的。给的训练数据像上图右下角那个图。 一个说话人有很多段音频,给出了音频的地址和长度。我们取一部分作为训练集,剩下的作为验证。

  下面是一个读文件的函数。

def readTrainMel(dataDir):map_path = Path(dataDir) / 'mapping.json'mapping = json.load(map_path.open())print(mapping)speaker2id, id2speaker = mapping.values()x = []y = []val_x = []val_y = []dataPath = Path(dataDir) / 'metadata.json'data = json.load(dataPath.open())speakers = data['speakers']for speaker in speakers:speakerList = speakers[speaker]for each in speakerList:x.append((each['feature_path'], each['mel_len']))y.append(speaker2id[speaker])return x, y

 speaker2id, id2speaker  这两个是标签和发言者id的转换。 最后我们记录下发言人每条发言的地址和这条地址对应的标签(发言者)。比如如果一个发言人他有10条数据,我们就记录10个语音的地址,这10个地址都对应着标签X。 

下面是dataset。


class speakerData(Dataset):def __init__(self, dataDir, mode='train', segment_len=256, x=None , y= None):super(speakerData, self).__init__()self.segment_len = segment_lenself.dataDir = dataDirself.mode = modemap_path = Path(dataDir) / 'mapping.json'mapping = json.load(map_path.open())print(mapping)speaker2id, id2speaker = mapping.values()if mode == 'train':self.x = xself.y = torch.LongTensor(y)elif mode == 'test':x = []dataPath = Path(dataDir) / 'testdata.json'data = json.load(dataPath.open())n_mels = data['n_mels']utterances = data['utterances']for utterance in utterances:x.append((utterance['feature_path'], utterance['mel_len']))self.x = xself.id2speaker = id2speakerdef __getitem__(self, item):uttrPath = os.path.join(self.dataDir ,self.x[item][0])uttrData = torch.load(uttrPath)n_mel = self.x[item][1]if self.mode == 'train':if n_mel > self.segment_len:start = random.randint(0, n_mel-self.segment_len)end = start + self.segment_lenuttrData = uttrData[start: end]if self.mode == 'test':segment_len = 2000if n_mel > segment_len:start = random.randint(0, n_mel-self.segment_len)end = start + self.segment_lenuttrData = uttrData[start: end]if self.mode == 'train':return uttrData, self.y[item]elif self.mode == 'test':return self.x[item][0], uttrDatadef __len__(self):return len(self.x)

dataset中都是比较平常的地方。值得注意的地方有: 

x中存储的是文件名,所以要根据文件名找到那个文件,读出数据。

seg_len需要自己设置 。官方的128就挺好的。 当训练或者验证的长度超过他,就裁剪为128。当测试的时候, 可以选择不裁剪,但是不裁剪有时候会出现爆内存的情况(如果你的编码维度高的话)。因为有些人的说话长度高达三四千。 可怕。 所以我裁剪了2000的长度。 

看loader 

def my_clooate(batch):mel, speaker = zip(*batch)mel = pad_sequence(mel,batch_first=True,padding_value=-20)return mel, torch.LongTensor(speaker)def inference_collate_batch(batch):"""Collate a batch of data."""feat_paths, mels = zip(*batch)return feat_paths, torch.stack(mels)def getDataloader(path, batchSize, mode):if mode == 'train' :x , y = readTrainMel(path)dataset = speakerData(path, mode='train', x=x, y=y)trainlen = int(0.9 * len(dataset))lengths = [trainlen, len(dataset) - trainlen]train_set, val_set = random_split(dataset, lengths)train_loader = DataLoader(train_set, batchSize, shuffle=True,collate_fn=my_clooate)val_loader = DataLoader(val_set, batchSize, shuffle=True,collate_fn=my_clooate)return train_loader, val_loaderelif mode == 'test':dataset = speakerData(path, mode=mode)test_loader = DataLoader(dataset, 1, shuffle=False,collate_fn=inference_collate_batch)return test_loader

步骤就是 先读出来x和y 然后分割成训练和验证。(话说这个分割函数我还是第一次见 ,从官方代码学的)  loader读进去。 注意collate_fn这个函数的作用是来组织bat内数据的。一般是默认的,就是把很多数据分别合起来。 在这里自己定义了,因为我们超过128的数据都被裁剪了 ,那么不足128的呢,必须补足128.因为batch内数据长度必须相同。  test时 bat为1 就不用补了 .

数据部分就是这个样字。 当你把文件读入后,会发现一个语音feature 一般是X*40 比如 600*40.40就是一个特征维度。 然后裁剪后变成128*40 变成batch 就是B*28*40. 然后输入到模型中去

2 模型准备:

       官方的模型是这样的                 

class 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.08100self.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(),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

先是一个prenet把数据从40维度转到80维度, 然后是transformer的编码,最后是预测层。一层mlp加上一个linear。 注意在前向的时候,transformer模型需要进行一个维度的转换。从BLD(batch,长度,维度)转换到LBD.其实我有点不理解这样的转换。而且有一些transformer模块也不需要这样的转换。 之后有一个平均池化,将trans的输出在长度上平均。平均后输出预测。 其实我一直觉得平均不太好,因为你说一个很大,一个很小,这样岂不是和都差不多得到的结果一样了?? 

      下面是我用的模型 。

class Classifier2(nn.Module):def __init__(self, d_model=512, 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.08100self.blocks = nn.ModuleList([ConformerBlock(dim=d_model,dim_head=64,heads=8,ff_mult=4,conv_expansion_factor=2,conv_kernel_size=15,attn_dropout=dropout,ff_dropout=dropout,conv_dropout=dropout)for i in range(6)])self.pooling = self_Attentive_pooling(d_model)self.pred_layer = AMSoftmax(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)for blk in self.blocks:out = blk(out)stats = self.pooling(out)# out: (batch, n_spks)out = self.pred_layer(stats)return out

如果你把d_model调节的很小 ,比如80, 128,那么你会得到一个训练集准确度百分之99,验证集90的结果。 但是线上提交结果只有70多。 

 如果你把d_model调节的很大 ,比如512,那么你会得到一个训练集准确度百分之90,验证集85的结果。 但是线上提交结果有80多。 

 但是有时候也不一定 , 神经网络 真的是玄学, 我都服了 说实话,,,。

这件事情挺令人疑惑的。写到这里 我决定再跑一次。

下面是模型中的一些模块 ,都来自大神, encore 大佬 和李宏毅助教的讲述

【ML2021李宏毅机器学习】作业4 Speaker Classification 思路讲解_哔哩哔哩_bilibili

conformer block 来源于 

   Conformer: Convolution-augmented Transformer for Speech Recognition

他的做法就是把单纯的transformer层换成右边的层。

本身多头注意力后面就应该直接输出进feed的 ,他加了一个卷积模块在中间,这样可以让模型在关注全局特征的时候也关注一下局部的特征。

 

 我用的时候发现一层不是很够啊 所以就垒了很多层。

self_Attentive_pooling  

class self_Attentive_pooling(nn.Module):def __init__(self, dim):super(self_Attentive_pooling, self).__init__()self.sap_linaer = nn.Linear(dim, dim)self.attention = nn.Parameter(torch.FloatTensor(dim,1))torch.nn.init.normal_(self.attention, std=.02)print(1)def forward(self, x):# x = x.permute(0, 2, 1)h = torch.tanh(self.sap_linaer(x))w = torch.matmul(h, self.attention).squeeze(dim=2)w = F.softmax(w, dim=1).view(x.size(0), x.size(1), 1)x = torch.sum(x * w, dim=1)return x

就是我上面谈到的问题了 ,对于一个bert的输出,一般是batch*length*dim.如果你直接mean,那两个5和一个0一个10的结果是一样的。这样会觉得不符合人的直觉。 所以也有用第一个token分类的,取 out[:,0,:]。。 这里的SELF——attpooling 的意思是,对于每一个特征,根据他自己的特征算出该给他赋予的权重。

AMsoftmax : Additive Margin Softmax for Face Verification


class AMSoftmax(nn.Module):def __init__(self, in_feats, n_classes, m=0.3, s=15, annealing=False):super(AMSoftmax, self).__init__()self.linaer = nn.Linear(in_feats, n_classes, bias=False)self.m = mself.s = sdef _am_logsumexp(self, logits):max_x = torch.max(logits, dim=-1)[0].unsqueeze(-1)term1 = (self.s*(logits - (max_x + self.m))).exp()term2 = (self.s * (logits - max_x)).exp().sum(-1).unsqueeze(-1) - (self.s*(logits-max_x)).exp()return self.s * max_x + (term2 + term1).log()def forward(self, *inputs):x_vector = F.normalize(inputs[0], p=2, dim=-1)self.linaer.weight.data = F.normalize(self.linaer.weight.data, p=2,dim=-1)logits = self.linaer(x_vector)scaled_logits = (logits-self.m)*self.sreturn scaled_logits - self._am_logsumexp(logits)

amsoftmax的功能是 让类内的特征靠的更近, 类外的离得更远 。怎么实现的呢 ?

 别问我 ,我也看不懂。用就完事了 ..............

训练 : 

        训练到现在已经没啥好说的了,训就完事了。

其他

这个作业的主要点也就是这些。 我也不知道怎么提点了。可能有些手段还可以提点 ,比如调参。但是计算资源真的不能供应我尝试。

其他模块跟前几次作业是一样的啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/60800.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php老师的一个作业展示

1.在ScanCode.php中 在judgeTrayCodeEnableIntoWarehouse方法中: 2在CommitTrayCodes.php中 访问时,直接访问CommitTrayCodes.php,这个CommitTrayCodes.php是要建在controller下,建议导一下,老师的数据库,以防止命名…

HCIA网络课程第七周作业

(1)请用自己的语言描述基本ACL和高级ACL的区别 (2)AAA支持的认证、授权和计费方式分别有哪几种? AAA支持的认证方式有不认证 本地认证 远端认证AAA支持的授权方式为不授权 本地授权 远端授权AAA支持计费方式为不计费…

如何获取抖音和快手直播间的直播流地址

如下是通过python代码脚本获取的方法: import requests import re def get_real_url(rid): try: if ‘v.douyin.com‘ in rid: room_id re.findall(r‘(\d{19})‘, requests.get(urlrid).url)[0] else: room_id rid room_url ‘https://webcast-hl.amemv.com/…

新手如何做抖音直播带货?新号如何快速获取直播推荐流量?

如果要做抖音直播带货的话,首先需要开通抖音直播带货权限。也就是我们经常说的解锁抖音直播购物车功能。解锁直播购物车后,我们就能在直播中售卖商品。 而在此之前,你要先开通商品橱窗并解锁视频购物车。开通商品橱窗,在完成新手…

抖音直播如何获取推流地址?不到1000粉也能直播啦。还能加热。2020年12月29日

抖音直播自从出了自己的pc客户端(直播伴侣)后,直播推流地址已不再对外暴漏。 正常情况下,粉丝大于1000,才可使用抖音官方的推流工具(直播伴侣)。但对于粉丝数不够1000,也想用第三方推流工具(如…

短视频、直播平台——电商直播源码第三方SDK接入教程

现在网络视频直播行业非常火爆,所以很多公司也希望开发直播平台,一般直播平台需要用户给主播送礼物来实现盈利,所以刷礼物的功能是必备的,另外为了增加视频的美感与炫酷等特效功能,也需要用到美颜与视频滤镜等功能&…

2022-5月如何使用疯狂URL获取抖音推流码地址(抖音无人直播教程)

什么是推流地址?平时我们如果是下载直播,叫拉流。但如果是你自己要直播,属于上传直播流数据,叫推流,即:把直播流数据推送到视频服务器,然后别人才能看到直播画面 推流地址有什么用?…

抖音短视频开通PC电脑上直播技术实现

忽如一夜春风来,直播带货满地开。互联网的江湖,是游戏的,是广告的,是直播的,是短视频的,但是归根结底是卖货的——也就是电商啦。 2020年可以看出短视频带货是未来大方向的趋势,最新抖音直播带货…

obs多路推流的实现,抖音直播、快手、淘宝、拼夕夕多平台一个画面同时直播,无人直播

最近最火的软件,无非抖音。抖音最火的内容无非是直播带货,而直播带货的平台有抖音、快手、淘宝、拼夕夕。 直播少不了主播,请一个主播不容易,可能月薪几万,成本较高。而如果自己培养一个主播,成功的概率较…

无人直播带货怎么操作:抖音无人直播视频素材+技术教程+软件工具

通过本文循序渐进的抖音无人直播实操技术指南,了解如何在抖音上编辑视频并让它大放异彩。      几年前,学习如何在抖音上编辑视频可能不是你想做的事情,但在社会最混乱的年份之一,抖音却从中受益。作为App Store和Google Play…

元宇宙| 用虚拟人进行抖音/快手直播

在上一篇文章零基础开启元宇宙——创建虚拟形象中,我们实现了创建虚拟形象,接下来我们可以利用虚拟形象“为所欲为”。今天我们利用虚拟形象在短视频平台如快手、抖音中直播,对于不希望露脸的主播们这是可是一大利器呀!话不多说&a…

抖音直播数据分析,通过千场直播深入解读直播间自然流量转化率

关于直播带货中的直播间流量,年前飞瓜智投介绍过付费流量和自然流量,以及直播间自然流量转化率,今天我们根据近千场直播累计的大数据来剖析一下,深入解读抖音直播间自然流量转化率。 付费流量作为直播间的一种推广产品&#xff0c…

乐山持点电商:抖音商家群聊群直播通知使用指南

抖音开启群直播通知后,只要商家一开播,系统自动抓取直播间信息,在商家粉丝群内进行开播提醒、热卖商品提醒、直播间权益提醒,将群成员引导进商家直播间,进行成交转化。 一、功能作用 直播推送升级:开播提醒…

云控系统+海外抖音TikTok直播公会,让直播变得更加容易

朋友们,大家好,欢迎来到元柚话TK,我是元柚,我会在这里持续分享有关TikTok的相关资讯,教大家如何从零基础到精通TikTok,也欢迎大家在评论区跟我交流。 好了,今天,我们聊聊TikTok直播&…

小程序直播如何接入抖音直播

废话不多说,直接上操作 第一步:先微信后台开一个直播房间 步骤 小程序对接第三方推流; 第二步:去打开抖音直播 复制链接 页面打开: 如图: #在抖音,记录美好生活#【看看新闻Knews】正在直播,来和我一起支持TA吧。复制下方链接,打开【抖音】&…

抖音快手如何轻松接入虚拟人直播

在上一篇文章零基础开启元宇宙——创建虚拟形象中,我们实现了创建虚拟形象,接下来我们可以利用虚拟形象“为所欲为”。今天我们利用虚拟形象在短视频平台如快手、抖音中直播,对于不希望露脸的主播们这是可是一大利器呀!话不多说&a…

开利成为独立上市公司,其股票开始在纽约证券交易所交易

Carrier Global Corporation成功从联合技术公司(United Technologies)分离出来,今天作为一家独立的上市公司首次亮相。Carrier是全球领先的建筑和制冷解决方案提供商,公司股票将在纽约证券交易所(NYSE)开始“常规”交易, 交易代码为“CARR”。 Carrier是…

海外问卷调查答题技巧,纯干货分享,新手小白看过来

海外问卷调查为什么别人赚得盆满钵满而我却连通过都不行?是不是经常有人发出这种疑问,东哥作为一个结交过很多做问卷调查行业的跨境人士,也了解到很多做这一行的去答题的时候都是掌握一定技巧的,而不是去乱答。 今天东哥就来说说国…

微信小程序做一个调查问卷(二)

即将不定期的开放代码 核心代码呈现源码下载在微信小程序如何展示富文本编辑器设置的内容多使用缓存技术,防止过多无效的访问题目分为单选题、多选题、简答题设置有其他选项,可进行手动输入选项多选题选择个数设置,只可最多选择三个 核心代码…

我想做国外问卷调查该怎么去入门?

目前2021年,很多的互联网创业项目横空出世。但是在这其中大家要有很好的眼光去识别并判断这个项目到底好不好呢?那我们该怎么样去判断这个呢,这是很多人存在疑惑的地方。 小编这里可以给大家说下咱们可以怎么样去判断一个创业项目的好与坏&am…