使用pyrouge计算ROUGE分数失败,报除零错误及subprocess异常
解决pyrouge调用ROUGE出现subprocess.CalledProcessError与除零错误的经验分享
我之前做文本摘要实验时也碰到过一模一样的问题,折腾了好一阵才搞定,大概率是文件名匹配逻辑、文件内容或者ROUGE环境依赖出了问题,下面是几个亲测有效的排查和解决方向:
1. 优先检查文件名ID匹配逻辑
你代码里的model_filename_pattern用了中文破折号——,而system_filename_pattern用的是下划线_,这很可能导致ROUGE无法正确匹配对应ID的参考文件和解码文件,最终因为没有有效数据计算触发除零错误:
- 确保参考文件和解码文件的ID完全对应,比如参考文件是
123_reference.txt,解码文件就得是123_decoded.txt,把model_filename_pattern改成和system端一致的分隔符:r.model_filename_pattern = '#ID#_reference.txt' # 把中文破折号换成下划线 - 验证正则匹配是否正确:比如解码文件名如果是
sample_456_decoded.txt,那system_filename_pattern要改成'sample_(\d+)_decoded.txt',保证能正确捕获ID数字。
2. 排查是否存在空文件
如果某个参考文件或解码文件是空的,ROUGE计算分数时会直接触发“Illegal division by zero”错误。可以加一段代码快速检查:
import os def check_empty_files(dir_path): empty_files = [] for filename in os.listdir(dir_path): file_path = os.path.join(dir_path, filename) if os.path.getsize(file_path) == 0: empty_files.append(filename) return empty_files print("参考目录空文件:", check_empty_files('/home/test/reference')) print("解码目录空文件:", check_empty_files('/home/test/decoded'))
如果发现空文件,要么补充内容,要么直接删除。
3. 验证ROUGE脚本的环境依赖
ROUGE-1.5.5依赖Perl的XML::Parser模块,有时候模块缺失会导致奇怪的子进程错误。你可以手动在终端执行报错里的ROUGE命令,看更详细的错误:
/home/username/env/ROUGE/RELEASE-1.5.5/ROUGE-1.5.5.pl -e /home/username/env/ROUGE/RELEASE-1.5.5/data -c 95 -2 -1 -U -r 1000 -n 4 -w 1.2 -a -m /tmp/tmpG9VKo9/rouge_conf.xml
如果提示缺少XML::Parser,用cpan安装即可:
cpan XML::Parser
4. 确认pyrouge的路径配置
有时候pyrouge没有正确指向ROUGE的安装目录,先重新配置路径再测试:
pyrouge_set_rouge_path /home/username/env/ROUGE/RELEASE-1.5.5
然后在Python里验证:
from pyrouge import Rouge155 r = Rouge155() print(r.rouge_path) # 输出应该是你的ROUGE安装目录
修改后的完整测试代码
把上面的检查逻辑加进你的代码里,方便提前排查问题:
from pyrouge import Rouge155 import os # 初始化ROUGE r = Rouge155() r.model_filename_pattern = '#ID#_reference.txt' r.system_filename_pattern = '(\d+)_decoded.txt' r.model_dir = '/home/test/reference' r.system_dir = '/home/test/decoded' # 1. 检查文件数量 model_files = [f for f in os.listdir(r.model_dir) if f.endswith('.txt')] system_files = [f for f in os.listdir(r.system_dir) if f.endswith('.txt')] print(f"参考文件数量: {len(model_files)}") print(f"解码文件数量: {len(system_files)}") # 2. 检查ID匹配 model_ids = {f.split('_')[0] for f in model_files} system_ids = {f.split('_')[0] for f in system_files} print(f"不匹配的ID: {model_ids.symmetric_difference(system_ids)}") # 3. 检查空文件 def check_empty(dir_path): return [f for f in os.listdir(dir_path) if os.path.getsize(os.path.join(dir_path, f)) == 0] print("参考目录空文件:", check_empty(r.model_dir)) print("解码目录空文件:", check_empty(r.system_dir)) # 4. 运行计算 rouge_results = r.convert_and_evaluate() print(rouge_results) output_dict = r.output_to_dict(rouge_results)
内容的提问来源于stack exchange,提问作者S.Chen
相关产品推荐
相关产品推荐

