自调ChatGPT 的口语练习Prompts分享(GPT 4.0、GPT 3.5 都可以用)

本文介绍如何使用语音助手进行IELTS英语口语模拟训练,步骤包括设置自定义指令,扮演教师角色提问并要求对每个回答进行修正,通过实际对话提升英语口语能力。
部署运行你感兴趣的模型镜像

Step1: Voice切换到Sky姐姐(好御 🥵bushi)

Step2: 打开Setting选择Custom Instructions输入以下内容:

Now you will play the role of an IELTS English speaking teacher, simulating a real scenario of conversation with me. All your questions will be described in English, and I will respond in English. We'll start with simple oral exercises and gradually increase the difficulty. Regardless of the information I input, you cannot deviate from the given scenario. Always maintain asking questions within the scenario to communicate with me, and polish my answers after each response.

Step3: 新建一个New Chat文字输入:

Could you please polish my answers after each response?

Step4: 点击耳机图标和Sky姐姐打招呼,等她和你聊天 😍

您可能感兴趣的与本文相关的镜像

GPT-oss:20b

GPT-oss:20b

图文对话
Gpt-oss

GPT OSS 是OpenAI 推出的重量级开放模型,面向强推理、智能体任务以及多样化开发场景

import datasets import transformers import modelscope from itertools import chain import glob import torch import evaluate from swanlab.integration.transformers import SwanLabCallback import swanlab import numpy as np from sklearn.metrics import accuracy_score import evaluate import transformers import torch import torch.nn as nn from transformers import AutoModelForCausalLM, GPT2Config from transformers import RobertaTokenizerFast # 实现旋转位置编码 class RotaryPositionalEmbedding(nn.Module): def __init__(self, dim, max_seq_len=2048, base=10000): super().__init__() self.dim = dim self.max_seq_len = max_seq_len self.base = base inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim)) self.register_buffer(&#39;inv_freq&#39;, inv_freq) self.register_buffer(&#39;positions&#39;, torch.arange(max_seq_len)) def forward(self, x): batch_size, seq_len, hidden_size = x.size() seq_len = min(seq_len, self.max_seq_len) positions = self.positions[:seq_len] angles = positions.unsqueeze(1) * self.inv_freq.unsqueeze(0) angles = angles.unsqueeze(0).repeat(batch_size, 1, 1) cos_angles = torch.cos(angles) sin_angles = torch.sin(angles) x_reshaped = x.view(batch_size, seq_len, -1, 2) x1, x2 = x_reshaped[..., 0], x_reshaped[..., 1] rotated_x1 = x1 * cos_angles - x2 * sin_angles rotated_x2 = x1 * sin_angles + x2 * cos_angles rotated = torch.stack([rotated_x1, rotated_x2], dim=-1).view(batch_size, seq_len, hidden_size) return rotated # 自定义模型类,继承自原模型的PreTrainedModel class CustomModelWithRotary(transformers.PreTrainedModel): config_class = GPT2Config def __init__(self, config): super().__init__(config) # 修改属性名避免与父类冲突 self.gpt2_model = transformers.AutoModelForCausalLM.from_pretrained( "/root/workspace/workspace/gpt2-large", config=config, ignore_mismatched_sizes=True ) self.rotary_emb = RotaryPositionalEmbedding( dim=config.hidden_size, max_seq_len=config.max_position_embeddings ) self.config.position_encoding_type = "rotary" def forward(self, input_ids=None, attention_mask=None, **kwargs): # 使用新的属性名调用模型 outputs = self.gpt2_model(input_ids=input_ids, attention_mask=attention_mask, **kwargs) if hasattr(outputs, &#39;last_hidden_state&#39;): outputs.last_hidden_state = self.rotary_emb(outputs.last_hidden_state) else: outputs = (self.rotary_emb(outputs[0]),) + outputs[1:] return outputs def main(): swanlab.init("PreTrain-GPT2-SELFIES") swanlab_callback = SwanLabCallback( project="PreTrain-GPT2-SELFIES", experiment_name="PreTrain-GPT2-SELFIES" ) raw_datasets = datasets.load_dataset( "json", data_files="/root/workspace/selfies1.json" ) # split dataset raw_datasets = raw_datasets["train"].train_test_split(test_size=0.05, seed=2333) print("dataset info") print(raw_datasets) saved_path = &#39;/root/workspace/robertatokenizer&#39; tokenizer = RobertaTokenizerFast.from_pretrained(saved_path) print("Loaded RobertaTokenizerFast from: " + saved_path) # 设置分词器的最大长度 tokenizer.model_max_length = 512 print(f"Set tokenizer model_max_length to: {512}") context_length = 512 # use a small context length) vocab_size = tokenizer.vocab_size print(f"Tokenizer vocab size: {vocab_size}") # preprocess dataset def tokenize(element): # 对数据集进行预处理,将文本转换为模型可以处理的输入格式 # 这里使用的是Qwen2-0.5B的Tokenizer,将文本转换为模型可以处理的输入格式 # truncation=True表示如果文本长度超过了context_length,就截断 # max_length=context_length表示文本的最大长度为context_length # return_overflowing_tokens=True表示返回溢出的tokens outputs = tokenizer( element["text"], truncation=True, max_length=context_length, return_overflowing_tokens=True, return_length=True, ) input_batch = [] # 作用是将溢出的tokens转换为模型可以处理的输入格式 # 这里使用的是Qwen2-0.5B的Tokenizer,将文本转换为模型可以处理的输入格式 # 这里的input_ids是一个二维数组,每一行表示一个文本的输入格式 # 这里的length是一个一维数组,每一个元素表示一个文本的长度 # 这里的input_batch是一个二维数组,每一行表示一个文本的输入格式 # 这里的context_length是一个整数,表示文本的最大长度 for length, input_ids in zip(outputs["length"], outputs["input_ids"]): if length == context_length: input_batch.append(input_ids) return {"input_ids": input_batch} # map函数的作用是将tokenize函数应用到数据集的每一个元素上 # batched=True表示将数据集分成batch进行处理 # remove_columns=raw_datasets["train"].column_names表示删除原始数据集的列名 tokenized_datasets = raw_datasets.map( tokenize, batched=True,num_proc=20, remove_columns=raw_datasets["train"].column_names ) print("tokenize dataset info") # print(tokenized_datasets) # eos_token的作用是表示文本的结束 # pad_token的作用是表示填充的token tokenizer.pad_token = tokenizer.eos_token # DataCollatorForLanguageModeling的作用是将数据集转换为模型可以处理的输入格式 # 这里使用的是Qwen2-0.5B的Tokenizer,将文本转换为模型可以处理的输入格式 # mlm=False表示不进行masked language modeling data_collator = transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False) # 加载配置 config = GPT2Config.from_pretrained("/root/workspace/workspace/gpt2-large") config.vocab_size = vocab_size # 更新配置中的 vocab_size # 检查配置中的 vocab_size print(f"Model config vocab size: {config.vocab_size}") # 直接实例化自定义模型,无需注册 model = CustomModelWithRotary(config) model_size = sum(t.numel() for t in model.parameters()) print("Model Config:") print(config) print(f"Model Size: {model_size/1000**2:.1f}M parameters") # 加载各个所需的指标 accuracy_metric = evaluate.load(&#39;./metrics/accuracy&#39;) def compute_metrics(eval_preds): logits, labels = eval_preds # 获取预测结果(取logits中概率最大的索引) preds = np.argmax(logits, axis=-1) # 形状: [batch_size, sequence_length] labels = labels[:, 1:].reshape(-1) preds = preds[:, :-1].reshape(-1) # 计算每个标记的准确度 accuracy = accuracy_metric.compute(predictions=preds, references=labels) return accuracy import random def compute_metrics_partial(eval_preds, subset_ratio=0.5): # 这里假设 eval_preds 是一个 list,包含 logits 和 labels logits, labels = eval_preds # 随机选择部分批次进行计算 batch_size = logits.shape[0] subset_size = int(batch_size * subset_ratio) # 计算子集的大小 selected_indices = random.sample(range(batch_size), subset_size) # 获取预测结果(只对选定的批次进行计算) selected_logits = logits[selected_indices] selected_labels = labels[selected_indices] preds = np.argmax(selected_logits, axis=-1) # shape: [subset_size, sequence_length] selected_labels = selected_labels[:, 1:].reshape(-1) selected_preds = preds[:, :-1].reshape(-1) # 计算准确度 accuracy = accuracy_metric.compute(predictions=selected_preds, references=selected_labels) return accuracy # train args = transformers.TrainingArguments( output_dir="./GPT2-SELFIES", per_device_train_batch_size=3, # 每个GPU的训batch数 per_device_eval_batch_size=3, # 每个GPU的测试batch数 eval_strategy="steps", eval_steps=2, logging_steps=5, gradient_accumulation_steps=8, # 梯度累计总数 num_train_epochs=100, # 训epoch数 lr_scheduler_type="cosine", # 学习率衰减策略 learning_rate=1e-5, # 基础学习率, save_steps=500, save_total_limit=10, bf16=True, # 开启bf16训, 对于Amper架构以下的显卡建议替换为fp16=True ) print("Train Args:") print(args) # enjoy training trainer = transformers.Trainer( model=model, tokenizer=tokenizer, args=args, data_collator=data_collator, train_dataset=tokenized_datasets["train"], eval_dataset=tokenized_datasets["test"], compute_metrics=compute_metrics, callbacks=[swanlab_callback], ) trainer.train() # save model trainer.save_model("./GPT2-SELFIES/Weight") # 保存模型的路径 # generate pipe = transformers.pipeline("text-generation", model=model, tokenizer=tokenizer) print("GENERATE:", pipe("人工智能", num_return_sequences=1)[0]["generated_text"]) prompts = ["牛顿", "北京市", "亚洲历史"] examples = [] for i in range(3): # 根据提示词生成数据 text = pipe(prompts[i], num_return_sequences=1)[0]["generated_text"] text = swanlab.Text(text) examples.append(text) swanlab.log({"Generate": examples}) if __name__ == "__main__": main()解决报错 File "/root/workspace/gpt2-large.py", line 247, in <module> main() File "/root/workspace/gpt2-large.py", line 228, in main trainer.train() File "/opt/conda/lib/python3.10/site-packages/transformers/trainer.py", line 2241, in train return inner_training_loop( File "/opt/conda/lib/python3.10/site-packages/transformers/trainer.py", line 2548, in _inner_training_loop tr_loss_step = self.training_step(model, inputs, num_items_in_batch) File "/opt/conda/lib/python3.10/site-packages/transformers/trainer.py", line 3698, in training_step loss = self.compute_loss(model, inputs, num_items_in_batch=num_items_in_batch) File "/opt/conda/lib/python3.10/site-packages/transformers/trainer.py", line 3759, in compute_loss outputs = model(**inputs) File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl return self._call_impl(*args, **kwargs) File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl return forward_call(*args, **kwargs) File "/opt/conda/lib/python3.10/site-packages/accelerate/utils/operations.py", line 819, in forward return model_forward(*args, **kwargs) File "/opt/conda/lib/python3.10/site-packages/accelerate/utils/operations.py", line 807, in __call__ return convert_to_fp32(self.model_forward(*args, **kwargs)) File "/opt/conda/lib/python3.10/site-packages/torch/amp/autocast_mode.py", line 16, in decorate_autocast return func(*args, **kwargs) File "/root/workspace/gpt2-large.py", line 68, in forward outputs = (self.rotary_emb(outputs[0]),) + outputs[1:] File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl return self._call_impl(*args, **kwargs) File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl return forward_call(*args, **kwargs) File "/root/workspace/gpt2-large.py", line 31, in forward batch_size, seq_len, hidden_size = x.size() not enough values to unpack (expected 3, got 0)
07-23
<think>我们遇到了一个新的错误:在RotaryPositionalEmbedding的forward函数中,尝试解包x.size()时,期望得到3个值(batch_size, seq_len, hidden_size),但实际上得到了0个值(即x是一个空张量?)。这通常意味着在某个地方我们传递了一个空的张量。 可能的原因: 1. 在训过程中,可能某个batch的数据为空(例如,在数据预处理时产生了空样本)。 2. 模型输出`outputs[0]`可能为空张量。 我们需要检查: - 数据预处理步骤是否可能产生空样本? - 模型在什么情况下会返回空张量? 但是,从错误堆栈来看,是在训过程中,调用`model(**inputs)`时,在自定义模型的forward函数中,对`outputs[0]`应用旋转位置编码时发生的。因此,我们需要确保`outputs[0]`不为空。 然而,我们注意到在自定义模型的forward函数中,我们有两种处理方式: if hasattr(outputs, &#39;last_hidden_state&#39;): ... else: ... (处理元组) 在else分支中,我们假设outputs是一个元组,并且第一个元素是hidden states(形状为[batch_size, seq_len, hidden_size])。但可能在某些情况下,这个元组的第一个元素是空的。 另外,我们也要检查数据,确保没有空batch。 但是,由于错误信息明确指出了是解包时数量不足,我们可以在RotaryPositionalEmbedding的forward函数中添加检查,避免处理空张量。 然而,更根本的可能是数据问题。我们可以在数据预处理步骤中检查是否有可能产生空列表?在tokenize函数中,我们只保留了长度等于context_length的样本。如果某个元素处理后没有这样的样本,那么input_batch可能为空,从而在后续形成空张量。 因此,我们需要在数据预处理时过滤掉空列表。 解决方案: 1. 在tokenize函数中,如果input_batch为空,则返回None,然后在map之后过滤掉这些None。 2. 在RotaryPositionalEmbedding的forward函数中,添加一个检查:如果x是空张量,则直接返回。 由于我们更希望从数据源头上避免空样本,因此我们选择在数据预处理时过滤掉空样本。 修改tokenize函数:如果input_batch为空,则返回一个空的字典(或者包含空列表的字典),然后使用datasets的filter函数过滤掉空列表。 具体步骤: 步骤1:修改tokenize函数,当input_batch为空时,返回一个特殊标记(例如,返回一个空列表的字典,但是这样在后续处理中仍然会被collator处理,所以最好是跳过这个样本) 步骤2:在map之后,使用filter函数过滤掉input_ids为空的样本。 但是,在tokenize函数中,我们返回的是{"input_ids": input_batch},而input_batch是一个列表。如果input_batch为空列表,那么这个样本就会变成{"input_ids": []},然后当我们使用DataCollatorForLanguageModeling时,它会跳过这个样本吗?实际上,DataCollatorForLanguageModeling会处理一个batch,如果遇到空列表,可能会出错。所以我们需要在数据集中删除这些样本。 因此,在map之后,我们可以添加一个过滤步骤: ```python tokenized_datasets = tokenized_datasets.filter(lambda example: len(example[&#39;input_ids&#39;]) > 0) ``` 但是,注意:我们的tokenize函数返回的每个样本实际上是一个列表(因为我们在batched=True模式下,每个样本是一个列表,每个元素是一个input_ids序列)。在map之后,每个样本的&#39;input_ids&#39;字段是一个列表,这个列表可能为空(表示这个原始样本没有产生任何长度等于context_length的片段)。因此,我们可以过滤掉那些&#39;input_ids&#39;字段为空的样本。 然而,在tokenize函数中,我们返回的每个样本的&#39;input_ids&#39;字段是一个列表,这个列表的长度表示该原始样本产生了多少个片段。如果为空,表示没有符合条件的片段,那么我们就应该删除这个样本(实际上是删除这个原始样本对应的所有片段,因为一个都没有)。 所以,在map之后,我们添加一行: ```python tokenized_datasets = tokenized_datasets.filter(lambda example: example[&#39;input_ids&#39;] != []) ``` 但是,注意:在tokenize函数中,我们返回的是{"input_ids": input_batch},而input_batch是一个列表,里面每个元素是一个input_ids序列(即一个片段)。如果input_batch为空,那么这个样本的&#39;input_ids&#39;字段就是空列表[]。 因此,我们可以这样过滤: ```python tokenized_datasets = tokenized_datasets.filter(lambda example: len(example[&#39;input_ids&#39;]) > 0) ``` 但是,请注意,在map之后,tokenized_datasets的每个样本的&#39;input_ids&#39;字段是一个列表(这个列表包含多个片段,每个片段是一个长度为context_length的列表)。所以,如果某个样本的&#39;input_ids&#39;字段为空列表,那么我们就过滤掉这个样本。 修改main函数中的代码: 在调用map之后,添加过滤: ```python tokenized_datasets = raw_datasets.map( tokenize, batched=True, num_proc=20, remove_columns=raw_datasets["train"].column_names ) # 过滤掉空样本 tokenized_datasets = tokenized_datasets.filter(lambda example: len(example[&#39;input_ids&#39;]) > 0) ``` 另外,为了安全起见,我们也可以在RotaryPositionalEmbedding的forward函数中添加一个检查: ```python def forward(self, x): # 如果x是空张量,直接返回 if x.numel() == 0: return x # 原来的代码 ... ``` 但是,如果数据预处理已经过滤了空样本,那么模型输入应该不会出现空张量。所以这一步可以不加,但加上更安全。 我们选择双管齐下。 修改RotaryPositionalEmbedding的forward函数: ```python def forward(self, x): # 检查x是否为空 if x.numel() == 0: return x batch_size, seq_len, hidden_size = x.size() # 原来的代码 ... ``` 这样,即使有空张量传入,我们也能安全处理。 总结修改点: 1. 在数据预处理后,过滤掉&#39;input_ids&#39;字段为空的样本。 2. 在RotaryPositionalEmbedding的forward函数开始处检查空张量。 修改后的代码: 在main函数中,map之后添加过滤: ```python tokenized_datasets = raw_datasets.map( tokenize, batched=True, num_proc=20, remove_columns=raw_datasets["train"].column_names ) print("tokenize dataset info") print(tokenized_datasets) # 过滤掉空样本 tokenized_datasets = tokenized_datasets.filter(lambda example: len(example[&#39;input_ids&#39;]) > 0) print("After filtering empty samples, dataset info:") print(tokenized_datasets) ``` 修改RotaryPositionalEmbedding的forward函数: ```python def forward(self, x): # 如果x是空张量,直接返回 if x.numel() == 0: return x batch_size, seq_len, hidden_size = x.size() seq_len = min(seq_len, self.max_seq_len) positions = self.positions[:seq_len] angles = positions.unsqueeze(1) * self.in_freq.unsqueeze(0) # 注意:这里应该是self.inv_freq,不是self.in_freq angles = angles.unsqueeze(0).repeat(batch_size, 1, 1) cos_angles = torch.cos(angles) sin_angles = torch.sin(angles) x_reshaped = x.view(batch_size, seq_len, -1, 2) x1, x2 = x_reshaped[..., 0], x_reshaped[..., 1] rotated_x1 = x1 * cos_angles - x2 * sin_angles rotated_x2 = x1 * sin_angles + x2 * cos_angles rotated = torch.stack([rotated_x1, rotated_x2], dim=-1).view(batch_size, seq_len, hidden_size) return rotated ``` 注意:上面代码中有一处笔误:`self.in_freq`应该为`self.inv_freq`。请修正。 另外,在数据过滤后,我们打印过滤后的数据集信息,以便确认。 如果问题仍然存在,我们可能需要检查数据预处理步骤,确保每个样本都正确生成。 但是,根据错误堆栈,问题发生在训过程中,所以可能是数据问题。我们通过过滤空样本应该可以解决。 让我们重新运行代码,看是否解决问题。 如果问题仍然存在,请提供新的错误信息。 注意:在数据预处理中,我们使用了`return_overflowing_tokens=True`,这可能会产生多个片段。但是,我们只保留了长度恰好等于context_length的片段。如果某个原始样本的所有片段都不等于context_length,那么它就会被过滤掉。这是正常的。 因此,我们按照上述修改代码。</think>错误表明在 `RotaryPositionalEmbedding.forward` 方法中尝试解包 `x.size()` 时遇到了空张量(0个值)。这通常发生在模型接收到无效输入或模型输出为空时。以下是完整的解决方案: ### 解决方案 #### 1. 修复空张量问题 在 `RotaryPositionalEmbedding.forward` 方法中添加空张量检查: ```python class RotaryPositionalEmbedding(nn.Module): # ... 保持其他代码不变 ... def forward(self, x): # 添加空张量检查 if x.numel() == 0: return x batch_size, seq_len, hidden_size = x.size() # ... 保持其他代码不变 ... ``` #### 2. 确保模型输入有效 在 `main()` 函数中添加数据有效性检查: ```python def main(): # ... 保持其他代码不变 ... # 在训前添加数据验证 def validate_data(dataset): for i in range(min(5, len(dataset))): # 检查前5个样本 sample = dataset[i] input_ids = sample["input_ids"] print(f"Sample {i} shape: {np.array(input_ids).shape}") assert len(input_ids) > 0, "发现空输入序列!" print("验证训数据...") validate_data(tokenized_datasets["train"]) print("验证测试数据...") validate_data(tokenized_datasets["test"]) # ... 保持其他代码不变 ... ``` #### 3. 修复模型输出处理 在 `CustomModelWithRotary.forward` 方法中添加输出验证: ```python class CustomModelWithRotary(transformers.PreTrainedModel): # ... 保持其他代码不变 ... def forward(self, input_ids=None, attention_mask=None, **kwargs): outputs = self.gpt2_model(input_ids=input_ids, attention_mask=attention_mask, **kwargs) # 验证输出有效性 if isinstance(outputs, tuple): hidden_states = outputs[0] if hidden_states.numel() == 0: print("警告: 模型输出为空张量!") return outputs elif hasattr(outputs, &#39;last_hidden_state&#39;): hidden_states = outputs.last_hidden_state if hidden_states.numel() == 0: print("警告: 模型输出为空张量!") return outputs else: print(f"未知输出类型: {type(outputs)}") return outputs # 应用旋转位置编码 if hasattr(outputs, &#39;last_hidden_state&#39;): outputs.last_hidden_state = self.rotary_emb(outputs.last_hidden_state) else: outputs = (self.rotary_emb(outputs[0]),) + outputs[1:] return outputs ``` ### 问题分析与解释 1. **问题原因**: - 模型接收到空输入序列(长度为零的输入) - 模型输出为空张量(可能是由于无效输入或模型内部错误) - 旋转位置编码层尝试处理空张量导致解包错误 2. **解决方案原理**: - 在旋转位置编码层添加空张量检查,避免处理无效输入 - 添加数据验证步骤,确保训/测试数据有效 - 在模型前向传播中添加输出验证,捕获潜在问题 3. **完整修复代码**: ```python class RotaryPositionalEmbedding(nn.Module): def __init__(self, dim, max_seq_len=2048, base=10000): super().__init__() self.dim = dim self.max_seq_len = max_seq_len self.base = base inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim)) self.register_buffer(&#39;inv_freq&#39;, inv_freq) self.register_buffer(&#39;positions&#39;, torch.arange(max_seq_len)) def forward(self, x): # 关键修复:添加空张量检查 if x.numel() == 0: return x batch_size, seq_len, hidden_size = x.size() seq_len = min(seq_len, self.max_seq_len) positions = self.positions[:seq_len] angles = positions.unsqueeze(1) * self.inv_freq.unsqueeze(0) angles = angles.unsqueeze(0).repeat(batch_size, 1, 1) cos_angles = torch.cos(angles) sin_angles = torch.sin(angles) x_reshaped = x.view(batch_size, seq_len, -1, 2) x1, x2 = x_reshaped[..., 0], x_reshaped[..., 1] rotated_x1 = x1 * cos_angles - x2 * sin_angles rotated_x2 = x1 * sin_angles + x2 * cos_angles rotated = torch.stack([rotated_x1, rotated_x2], dim=-1).view(batch_size, seq_len, hidden_size) return rotated class CustomModelWithRotary(transformers.PreTrainedModel): config_class = GPT2Config def __init__(self, config): super().__init__(config) self.gpt2_model = transformers.AutoModelForCausalLM.from_pretrained( "/root/workspace/workspace/gpt2-large", config=config, ignore_mismatched_sizes=True ) self.rotary_emb = RotaryPositionalEmbedding( dim=config.hidden_size, max_seq_len=config.max_position_embeddings ) self.config.position_encoding_type = "rotary" def forward(self, input_ids=None, attention_mask=None, **kwargs): outputs = self.gpt2_model(input_ids=input_ids, attention_mask=attention_mask, **kwargs) # 关键修复:添加输出验证 if isinstance(outputs, tuple): hidden_states = outputs[0] if hidden_states.numel() == 0: print("警告: 模型输出为空张量!") return outputs elif hasattr(outputs, &#39;last_hidden_state&#39;): hidden_states = outputs.last_hidden_state if hidden_states.numel() == 0: print("警告: 模型输出为空张量!") return outputs else: print(f"未知输出类型: {type(outputs)}") return outputs if hasattr(outputs, &#39;last_hidden_state&#39;): outputs.last_hidden_state = self.rotary_emb(outputs.last_hidden_state) else: outputs = (self.rotary_emb(outputs[0]),) + outputs[1:] return outputs ``` ### 额外调试建议 1. 添加更详细的数据验证: ```python def validate_data(dataset): empty_count = 0 for i in range(len(dataset)): sample = dataset[i] input_ids = sample["input_ids"] if len(input_ids) == 0: empty_count += 1 print(f"空样本索引: {i}") print(f"总样本数: {len(dataset)}, 空样本数: {empty_count}") assert empty_count == 0, f"发现 {empty_count} 个空样本!" ``` 2. 添加模型调试回调: ```python class DebugCallback(transformers.TrainerCallback): def on_step_begin(self, args, state, control, **kwargs): inputs = kwargs.get("inputs", {}) print(f"Step {state.global_step} - 输入形状: {inputs[&#39;input_ids&#39;].shape}") def on_step_end(self, args, state, control, **kwargs): outputs = kwargs.get("outputs", {}) if hasattr(outputs, "loss"): print(f"Step {state.global_step} - 损失: {outputs.loss.item()}") # 在Trainer中添加回调 trainer = transformers.Trainer( # ... 其他参数 ... callbacks=[swanlab_callback, DebugCallback()], ) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值