神经网络语言模型的效果不及预期

如何解决神经网络语言模型的效果不及预期

我正在尝试使用神经网络来实现一些相对标准的语言模型,以更好地理解它们,并希望将来使它们适应其他问题。我一直在使用WikiText-2数据集,以便可以将结果与现有基准进行比较。到目前为止,我已经实现了一个简单的RNN模型(使用LSTM或GRU单元),以及一个使用TensorFlow 2的基于变压器的模型。

我还没有对超参数进行广泛或系统的研究,但经过摆弄,我无法在验证数据集(对于任何一个模型)上使混淆度远低于220-240。鉴于已发布的报告,这几乎不及我预期的那样。例如,我希望LSTM达到100左右。

我怀疑在数据处理或模型结构中肯定存在错误,无效的假设或缺少的步骤。有很多代码,所以我不会全部发布,但是我将尝试包括相关部分。

编辑:我已经上传了转换器模型here的完整实现。 除了下面的观察,我还注意到val_lossval_xent之间的区别,我无法解释。其中val_lossval_xent都是分类交叉熵的掩蔽版本,但是一个是Keras Loss的子类,一个是Keras Metric的子类。

数据处理

我对数据集的理解是,为了测试模型学习长距离依赖项的能力,基本上应该将其视为一个连续的长文本。从理论上讲,可以将其分解为单独的文档,但是我发现准确地确定文档边界并不是一件容易的事。似乎前导和尾随=表示一篇新文章,但是该规则有一些例外。因此,我只是忽略了文章的边界,而是将文件视为一个连续的长文本。从理论上讲,模型应该了解=符号的含义。

由于模型只能在有限长度的序列上工作,因此我将数据集分成固定大小的片段,这将是模型的序列长度。下面的代码实现了这些假设。我怀疑这是否可扩展,但它适用于像这样的较小数据集。

# Load a dataset from the WikiText file
dataset = tf.data.TextLineDataset(path_to_wiki_file.tokens)

# Strip leading and trailing whitespace from each line
dataset = dataset.map(tf.strings.strip)

# Remove blank lines
dataset = dataset.filter(lambda line: tf.not_equal(tf.strings.length(line),0))

# Split the tokens on whitespace
dataset = dataset.map(tf.strings.split)

# Create one long sequence from the input
dataset = dataset.unbatch()

# Map the string token to a unique integer id (starting at 1).
# word2id is a tf.lookup.StaticHashTable
dataset = dataset.map(lambda t: word2id.lookup(t)

# Create fixed length pieces
dataset = dataset.window(seq_len+1)
dataset = dataset.flat_map(lambda w: w.batch(seq_len+1))

# Note I've also tried randomly selecting arbitrary windows of the
# text during training,which seems to improve performance to a 
# small degree.
# The implementation is also not efficient,but works ok for this
# dataset. Something like:
# dataset = dataset.window(seq_len,shift=1)
# dataset = dataset.flat_map(lambda w: w.batch(seq_len))
# And then randomly selecting a subset of them

# Create the x,y pairs
dataset = dataset.map(lambda t: (t[:-1],t[1:])

# Cache the preprocessing steps
dataset = dataset.cache()

# Create the batches,padding if necessary (although only the
# last batch should need to be padded)
dataset = dataset.padded_batch(bsz,padded_shapes=(seq_len,seq_len))

基于RNN的模型

基于RNN的模型相当简短,易于解释。

import tf.keras.layers as tfl

class RnnLanguageModel(tf.keras.models.Model):
    def __init__(self,vocab_size,n_embedding_units,n_layers,n_units,**kwargs):
        super().__init__(**kwargs)

        # The layers are defined here.
        self.embedding_layer = tfl.Embedding(vocab_size,n_embedding_units)
        self.recurrent_layers = [
            tfl.LSTM(n_units,stateful=True,return_sequences=True) 
            for _ in range(n_layers)
        ]
        self.final_layer = tfl.Dense(vocab_size)

    def call(inputs,training):
        # Get the embeddings for the current input
        x = self.embedding_layer(inputs)
        
        # Apply the recurrent layers
        for layer in self.recurrent_layers:
            x = layer(x)

        # A final dense layer that outputs the final predictions.
        logits = self.final_layer(x)

        return logits

基于变压器的模型

有太多代码可以在此处发布,但几乎所有内容都是从TensorFlow tutorial on Transformers开始的。我对模型所做的唯一重大更改是在DecoderLayer中。由于我们没有来自编码器的输入,因此注意模块之一不适用。因此,我的解码器层的调用函数如下所示:

def call(self,x,training,look_ahead_mask):
    # enc_output.shape == (batch_size,input_seq_len,n_model_dim)

    # (batch_size,target_seq_len,n_model_dim)
    attn,attn_weights_block = self.mha1(x,look_ahead_mask)
    attn = self.dropout1(attn,training=training)
    out = self.layer_norm1(attn + x)

    # There isn't an encoder so we don't need the other layers used
    # in the transformer tutorial.

    # (batch_size,n_model_dim)
    ffn_output = self.ffn(out)
    ffn_output = self.dropout2(ffn_output,training=training)

    # (batch_size,n_model_dim)
    result = self.layer_norm2(ffn_output + out)  

    return result,attn_weights_block

观察

除了无法达到预期的困惑之外,我在实现过程中还注意到了一些事情。

变压器似乎对某些超参数极为敏感,而对其他一些参数则完全不敏感。例如,如果层数太多或模型尺寸太大,则模型将根本不学习任何东西。另一方面,更改序列长度,头数和前馈单元似乎并没有太大的区别(这有所区别,只是几乎没有我的期望)。

我还注意到,用于翻译的原始论文的自定义学习率时间表似乎根本无法解决此问题(至少使用默认参数)。

任何帮助或见解将不胜感激。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-