CPC模型源码阅读

CPC模型源码阅读

  • 将高维数据压缩到更紧凑的隐空间中,在其中条件预测更容易建模。

  • 我们使用强大的自回归模型在这个隐空间中预测未来的许多步骤

  • 依靠噪声对比估计(Noise-Contrastive Estimation) 来计算损失函数(和自然语言模型中的学习单词嵌入方式类似),从而可以对整个模型进行端到端的训练。

  • 最终提出的 Contrastive Predictive Codeing(CPC)方法可以用相同的机制在图像、语音、自然语言、强化学习等多个模态的数据上都能学习到高级信息。

  • I(x,c) = H(x) - H(x|c) 说明了x和c的互信息表示由于c的引入而使得x熵减小的量,也就是x不确定度减小的量

  • 那么最大化I(x,c)就是通过充分学习现在的上下文c最大程度减小了未来x的不确定度,从而起到了预测的效果,所以cpc希望网络可以最大化x和c之间的互信息

  • 它可以用于序列数据,也可以用于图片

  • CPC的目标就是要做unsupervised representation learning,并且我们希望这个representation有很好的predictive的能力。

github:https://github.com/jefflai108/Contrastive-Predictive-Coding-PyTorch

model.py


"""
cpc 原始模型
"""
class CDCK2(nn.Module):# timestep时间步数 batch 批量大小  seq_len 序列长度def __init__(self, timestep, batch_size, seq_len):super(CDCK2, self).__init__()self.batch_size = batch_sizeself.seq_len = seq_lenself.timestep = timestepself.encoder = nn.Sequential( # downsampling factor = 160nn.Conv1d(1, 512, kernel_size=10, stride=5, padding=3, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=8, stride=4, padding=2, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=4, stride=2, padding=1, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=4, stride=2, padding=1, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=4, stride=2, padding=1, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True))self.gru = nn.GRU(512, 256, num_layers=1, bidirectional=False, batch_first=True)self.Wk  = nn.ModuleList([nn.Linear(256, 512) for i in range(timestep)])self.softmax  = nn.Softmax()self.lsoftmax = nn.LogSoftmax()def _weights_init(m):if isinstance(m, nn.Linear):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')if isinstance(m, nn.Conv1d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')elif isinstance(m, nn.BatchNorm1d):nn.init.constant_(m.weight, 1)nn.init.constant_(m.bias, 0)# initialize grufor layer_p in self.gru._all_weights:for p in layer_p:if 'weight' in p:nn.init.kaiming_normal_(self.gru.__getattr__(p), mode='fan_out', nonlinearity='relu')self.apply(_weights_init)def init_hidden(self, batch_size, use_gpu=True):if use_gpu: return torch.zeros(1, batch_size, 256).cuda()else: return torch.zeros(1, batch_size, 256)def forward(self, x, hidden):batch = x.size()[0]t_samples = torch.randint(self.seq_len/160-self.timestep, size=(1,)).long() # randomly pick time stamps# input sequence is N*C*L, e.g. 8*1*20480z = self.encoder(x)# encoded sequence is N*C*L, e.g. 8*512*128# reshape to N*L*C for GRU, e.g. 8*128*512z = z.transpose(1,2)nce = 0 # average over timestep and batchencode_samples = torch.empty((self.timestep,batch,512)).float() # e.g. size 12*8*512for i in np.arange(1, self.timestep+1):encode_samples[i-1] = z[:,t_samples+i,:].view(batch,512) # z_tk e.g. size 8*512forward_seq = z[:,:t_samples+1,:] # e.g. size 8*100*512output, hidden = self.gru(forward_seq, hidden) # output size e.g. 8*100*256c_t = output[:,t_samples,:].view(batch, 256) # c_t e.g. size 8*256pred = torch.empty((self.timestep,batch,512)).float() # e.g. size 12*8*512for i in np.arange(0, self.timestep):linear = self.Wk[i]pred[i] = linear(c_t) # Wk*c_t e.g. size 8*512for i in np.arange(0, self.timestep):total = torch.mm(encode_samples[i], torch.transpose(pred[i],0,1)) # e.g. size 8*8correct = torch.sum(torch.eq(torch.argmax(self.softmax(total), dim=0), torch.arange(0, batch))) # correct is a tensornce += torch.sum(torch.diag(self.lsoftmax(total))) # nce is a tensornce /= -1.*batch*self.timestepaccuracy = 1.*correct.item()/batchreturn accuracy, nce, hiddendef predict(self, x, hidden):batch = x.size()[0]# input sequence is N*C*L, e.g. 8*1*20480z = self.encoder(x)# encoded sequence is N*C*L, e.g. 8*512*128# reshape to N*L*C for GRU, e.g. 8*128*512z = z.transpose(1,2)output, hidden = self.gru(z, hidden) # output size e.g. 8*128*256return output, hidden # return every frame#return output[:,-1,:], hidden # only return the last frame per utt
self.batch_size = batch_size
self.seq_len = seq_len
self.timestep = timestep
  • 这一部分是CDCK2类的构造函数,用于初始化该模型的实例。输入参数包括时间步长(timestep),批处理大小(batch_size),以及序列长度(seq_len)
self.encoder = nn.Sequential( # downsampling factor = 160nn.Conv1d(1, 512, kernel_size=10, stride=5, padding=3, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=8, stride=4, padding=2, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=4, stride=2, padding=1, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=4, stride=2, padding=1, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Conv1d(512, 512, kernel_size=4, stride=2, padding=1, bias=False),nn.BatchNorm1d(512),nn.ReLU(inplace=True)
)
  • 这部分定义编码器encoder 他是一个nn.Sequential的模块,包含多个卷积层、批量标准化层、Relu激活函数。传入的一维数据按照顺序通过这些层处理
  • 每一个卷积层的目的是提取输入数据的特征,而批量标准化层用于加速训练过程并且改善模型的泛化能力
  • 最终编码器会对输入进行降采样,整体将采样率是160 由步长决定
self.gru = nn.GRU(512, 256, num_layers=1, bidirectional=False, batch_first=True)
  • 定义了一个单层、非双向的GRU循环神经网络,输入特征大小为512,隐藏层特征大小是256,并且批次大小指定在数据的第一维(batch_first=True),预测未来某个采样点的值
self.Wk = nn.ModuleList([nn.Linear(256, 512) for i in range(timestep)])
  • 初始化一个模块列表 ModuleList 包含多个线性层nn.Linear ,每一个时间步一个,这些线性层被用来预测未来时间步的特征。模块列表中每一个线性层wk将GRU的输出(256维)映射回编码器的特征维度512维度

self.softmax = nn.Softmax()
self.lsoftmax = nn.LogSoftmax()
  • 定义softmax和 log softmax 函数,用于计算预测值的概率分布和对数概率分布,常用于分类问题和多分类的交叉熵损失计算
def _weights_init(m):if isinstance(m, nn.Linear) or isinstance(m, nn.Conv1d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')elif isinstance(m, nn.BatchNorm1d):nn.init.constant_(m.weight, 1)nn.init.constant_(m.bias, 0)
  • 私有函数weights_init用于权重初始化,会被用到类中的所有模块上面,对于线性层和卷积层,它使用Kaiming_normal初始化方法,这个方法基于ReLu激活函数的特征设置权重,对于批量标准化层,则设置权重为1和偏置为0
self.apply(_weights_init)
  • 这行代码应用_weights_init函数到模块的每一个子模块,即对self模块中所有子模块初始化其权重。
def init_hidden(self, batch_size, use_gpu=True):if use_gpu: return torch.zeros(1, batch_size, 256).cuda()else: return torch.zeros(1, batch_size, 256)
  • init_hidden方法用于初始化GRU的隐藏层,这里返回一个全0的张量,其尺寸由GRU的层数,Batch和隐藏层特征大小
def forward(self, x, hidden):batch = x.size()[0]t_samples = torch.randint(self.seq_len/160-self.timestep, size=(1,)).long()
  • 前向传播逻辑
  • 确定批次大小和随机生成一个整数t_samples,该整数用于从序列中随机采样一个起始点,用于从编码器输出中提取时间步样本
z = self.encoder(x)
z = z.transpose(1,2)
  • 输出数据x通过编码器,并且转置层,以符合GRU输入的期望格式,这里假设x是一个三维张量,其中包含批次、通道数和长度维度
nce = 0 # average over timestep and batch
encode_samples = torch.empty((self.timestep, batch, 512)).float()
  • 初始化变量nce为0 该变量用于累计归一化交叉熵损失
  • 初始化encode_samples张量以保存编码器输出中提取的样本,它们之后用于计算NCE损失
for i in np.arange(1, self.timestep+1):encode_samples[i-1] = z[:, t_samples+i, :].view(batch, 512)
forward_seq = z[:, :t_samples+1, :]
  • 在这个循环中,对于每一个时间步,从编码之后的数据z中选择特定的样本,并将它们存储在encode_samples张量中,同时,我们也创建了一个forward_seq变量,它包含从序列开始到随机选择的时间戳中的所有编码数据
output, hidden = self.gru(forward_seq, hidden)
c_t = output[:, t_samples, :].view(batch, 256)
  • forward_seq和隐藏状态传递给GRU层,并且计算输出和新的隐藏状态
  • c_t包含了GRU输出的当前时刻的状态,用于预测未来的状态
pred = torch.empty((self.timestep, batch, 512)).float()
for i in np.arange(0, self.timestep):linear = self.Wk[i]pred[i] = linear(c_t)
  • 初始化pred张量,用于存储对未来时间步的预测
  • 对于每个时间步,使用对应的线性层wk[i] 从当前状态c_t计算预测值,并且将结果保存在pred中
for i in np.arange(0, self.timestep):total = torch.mm(encode_samples[i], torch.transpose(pred[i], 0, 1))correct = torch.sum(torch.eq(torch.argmax(self.softmax(total), dim=0), torch.arange(0, batch)))nce += torch.sum(torch.diag(self.lsoftmax(total)))
nce /= -1.*batch*self.timestep
accuracy = 1.*correct.item()/batch
  • 对于每个时间步长,计算真实的样本encode_samples[i] 与预测值pred[i] 之间的softmax分数
  • 然后找出正确的预测correct,并且将这一个信息用于计算批次的精度accuracy
  • nce变量被用来计算向量total对角线上每一个元素的log softmax和,它用于计算归一化交叉熵损失
def predict(self, x, hidden):batch = x.size()[0]z = self.encoder(x)z = z.transpose(1,2)output, hidden = self.gru(z, hidden)return output, hidden
  • predict方法的流程与forward类似,不过这里返回的是经过GRU处理之后的所有输出和最新的隐藏状态。这方便用于在验证阶段或者模型部署的时候进行序列预测

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

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

相关文章

Java计划线程池ScheduledThreadPoolExecutor运行流程和源码分析

1. 计划线程池ScheduledThreadPoolExecutor简介 ScheduledThreadPoolExecutor继承自线程池ThreadPoolExecutor,并在其基础上增加了按时间调度执行任务的功能,如果对ThreadPoolExecutor还不是很熟悉,可以阅读一下这篇文章: Java线…

【C++】---内存管理new和delete详解

一、C/C内存分布 C/C内存被分为6个区域: (1) 内核空间:存放内核代码和环境变量。 (2)栈区:向下增长(存放非静态局部变量,函数参数,返回值等等) …

OCPP 1.6 接入实现文档

一、简介 OCPP(Open Charge Point Protocol)是一个开放的通信协议,用于充电站(Charge Point)与中央系统(Central System,如充电站管理系统或服务提供商平台)之间的通讯。本篇文档将…

纽约纳斯达克大屏投放受众群体有哪些-大舍传媒

纽约纳斯达克大屏投放受众群体有哪些-大舍传媒 1. 纳斯达克大屏的概述 纳斯达克大屏是全球金融市场中最出名的电子交易平台之一。作为一个重要的金融信息传递渠道,纳斯达克大屏吸引了来自全球的投资者的目光。在这个巨大的投放平台上,大舍传媒希望为客…

【Java】线程池总结——干货满满!!!

目录 一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 1) 任务(Runnable /Callable) 2) 任务的执行(Executor) 3) 异步计算的结果(Future) 2.3 Executor 框架的使用示意图 三 (重要)ThreadPoolExecutor 类简单介绍 3.1 Thr…

一文说清VO,BO,PO,DO,DTO的使用场景

在 Java 开发中,VO、BO、PO、DO、DTO 和 Entity 是一些常见的命名约定,它们代表了不同的概念和在不同层次中使用的对象类型。下面我将简要介绍它们的区别,并举例说明: VO(View Object): 区别&…

如何使用Axure RP制作web页面并实现无公网ip远程访问——“cpolar内网穿透”

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

Vue知识学习

Vue 是什么? 概念:Vue 是一个用于构建用户界面的渐进式框架 Vue 的两种使用方式: ① Vue 核心包开发 场景:局部 模块改造 ② Vue 核心包& Vue插件工程化开发 场景:整站开发 创建Vue 实例,初始化渲染的核心步骤: 1.准备容器 2.引包(官…

基于java在线调查表单系统

基于java在线调查表单系统 一、演示效果二、特性汇总三、下载链接 一、演示效果 二、特性汇总 多种技术方案,满足不同的技术选型需求完善的浏览器兼容、保证传统客户也能正常使用部署简单,一行命令完成部署更新方便,直接替换原安装文件不用担…

F2图例封装 - BarAndLine

基于vue3 和 F2 3.5.0 <template><div :style"{minHeight: ${height}px,width: 100% }" ref"container"><canvas v-show"showChart" ref"canvas" :id"chartId" class"chart-canval"></canva…

【stm32】hal库-双通道ADC采集

【stm32】hal库-双通道ADC采集 CubeMX图形化配置 程序编写 /* USER CODE BEGIN PV */ #define BATCH_DATA_LEN 1 uint32_t dmaDataBuffer[BATCH_DATA_LEN]; /* USER CODE END PV *//* USER CODE BEGIN 2 */lcd_init();lcd_show_str(10, 10, 24, "Demo14_4:ADC1 ADC2 S…

微服务中排除父项目中的某个依赖

微服务中&#xff0c;子项目排除父项目中的某个依赖 在微服务项目中&#xff0c;可以通过使用maven的exclusions标签排除父项目中的某个依赖。具体操作如下&#xff1a; 打开子项目的pom.xml文件。 在子项目的dependency标签中&#xff0c;添加exclusions标签&#xff0c;指定…

Python 实现 BRAR 指标计算(情绪指标):股票技术分析的利器系列(11)

Python 实现 BRAR 指标计算&#xff08;情绪指标&#xff09;&#xff1a;股票技术分析的利器系列&#xff08;11&#xff09; 介绍算法公式 代码rolling函数介绍核心代码计算BR计算AR 完整代码 介绍 BRAR 是一种情绪指标&#xff0c;用于衡量特定金融市场中的买卖情绪。它代表…

牛客周赛34(A-E)

目录 1.A 2.B 3.C 4.D 5.E 这场出题人号称是考思维,把我给搞蒙了,把我这菜鸡实力暴露的淋漓尽致,不过这场还是让我学到了东西.A,B题就是签到题,会语法就能做(doge),c题我知道思路是啥,但我没想到切分出来的偶数也可能爆long long,所以还得用字符串存,自定义cmp比较函数,而我…

关于内容生成及其上下游的一些问题和想法以及SmartChat给出的答复

写在问题前面 下面的一系列问题&#xff0c;是为了要实现问题中所提到的内容而提出的。如果有感兴趣的朋友&#xff0c;让我们一起学习进步。同时&#xff0c;以下代码、架构和实现都是我计划想要完成的&#xff0c;如果有任何一方面有基础又愿意一起实现它们的请留言或私信一…

试一下newb,还是有错误呀

解题&#xff1a;原式&#xff1d; 2. 在递增的等比数列 ( a n ) (a_n) (an​)中&#xff0c;若 ( a 3 − a 1 5 2 ) (a_3 - a_1 \frac{5}{2}) (a3​−a1​25​), ( a 2 3 ) (a_2 3) (a2​3), 则公比 (q) A. ( 4 3 ) ( \frac{4}{3} ) (34​) B. ( 3 2 ) ( \frac{3}{2} …

netcat(nc)下载及基本使用

netcat&#xff08;nc&#xff09;下载及基本使用 - 知乎

旧物回收小程序开发,开启绿色生活新篇章

随着科技的发展和人们生活水平的提高&#xff0c;物质生活的丰富带来了大量的废弃物。如何合理处理这些废弃物&#xff0c;实现资源的再利用&#xff0c;已成为社会关注的焦点。旧物回收小程序的开发与应用&#xff0c;为这一问题提供了有效的解决方案。本文将探讨旧物回收小程…

软考47-上午题-【数据库】-数据查询语言DQL2

一、聚合函数 聚合函数实现数据统计的功能&#xff0c;返回一个单一的值。聚合函数一般与select语句的group by子句一起使用。 示例&#xff1a; 二、数据分组-group by 聚合函数加上group by子句进行分组。 通常一个聚合函数的作用范围是满足where子句中指定条件的记录&…

Atcoder ABC341 C - Takahashi Gets Lost

Takahashi Gets Lost&#xff08;高桥迷路了&#xff09; 时间限制&#xff1a;3s 内存限制&#xff1a;1024MB 【原题地址】 所有图片源自Atcoder&#xff0c;题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【…