Transformers 4.37 中文文档(十一)(1)https://developer.aliyun.com/article/1564970
运行文档测试
为了测试文档示例是否正确,您应该检查doctests
是否通过。例如,让我们使用WhisperModel.forward
的文档字符串:
r""" Returns: Example: ```python >>> import torch >>> from transformers import WhisperModel, WhisperFeatureExtractor 从数据集导入数据集 >>> model = WhisperModel.from_pretrained("openai/whisper-base") >>> feature_extractor = WhisperFeatureExtractor.from_pretrained("openai/whisper-base") >>> ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation") >>> inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt") >>> input_features = inputs.input_features >>> decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id >>> last_hidden_state = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state >>> list(last_hidden_state.shape) [1, 2, 512] ```py"""
只需运行以下行,自动测试所需文件中的每个文档字符串示例:
pytest --doctest-modules <path_to_file_or_dir>
如果文件具有 markdown 扩展名,应添加--doctest-glob="*.md"
参数。
仅运行修改后的测试
您可以通过使用pytest-picked来运行与未暂存文件或当前分支(根据 Git)相关的测试。这是一个快速测试您的更改是否破坏了任何内容的好方法,因为它不会运行与您未触及的文件相关的测试。
pip install pytest-picked
pytest --picked
将从已修改但尚未提交的文件和文件夹中运行所有测试。
在源代码修改时自动重新运行失败的测试
pytest-xdist提供了一个非常有用的功能,可以检测所有失败的测试,然后等待您修改文件并持续重新运行这些失败的测试,直到它们通过,同时您修复它们。这将重复进行,直到所有测试通过,之后再次执行完整运行。
pip install pytest-xdist
要进入模式:pytest -f
或pytest --looponfail
通过查看looponfailroots
根目录及其所有内容(递归)来检测文件更改。如果此值的默认值对您不起作用,您可以通过在setup.cfg
中设置配置选项来更改项目中的值:
[tool:pytest] looponfailroots = transformers tests
或pytest.ini
/tox.ini
文件:
[pytest] looponfailroots = transformers tests
这将导致仅查找相对于 ini 文件目录指定的相应目录中的文件更改。
pytest-watch是此功能的另一种实现。
跳过一个测试模块
如果您想运行所有测试模块,除了一些,您可以通过提供一个明确的测试运行列表来排除它们。例如,要运行除了test_modeling_*.py
测试之外的所有测试:
pytest *ls -1 tests/*py | grep -v test_modeling*
清除状态
CI 构建和隔离重要时(针对速度),应清除缓存:
pytest --cache-clear tests
并行运行测试
如前所述,make test
通过pytest-xdist
插件(-n X
参数,例如-n 2
以运行 2 个并行作业)并行运行测试。
pytest-xdist
的--dist=
选项允许控制如何对测试进行分组。--dist=loadfile
将位于一个文件中的测试放在同一个进程中。
由于执行测试的顺序不同且不可预测,如果使用pytest-xdist
运行测试套件会产生失败(意味着我们有一些未检测到的耦合测试),请使用pytest-replay以相同顺序重放测试,这应该有助于以某种方式将失败序列减少到最小。
测试顺序和重复
最好多次重复测试,按顺序、随机或成组进行,以检测任何潜在的相互依赖和与状态相关的错误(拆除)。直接的多次重复只是用来检测由于 DL 的随机性而暴露出的一些问题。
重复测试
pip install pytest-flakefinder
然后多次运行每个测试(默认为 50 次):
pytest --flake-finder --flake-runs=5 tests/test_failing_test.py
此插件不与pytest-xdist
的-n
标志一起使用。
还有另一个插件pytest-repeat
,但它与unittest
不兼容。
以随机顺序运行测试
pip install pytest-random-order
重要提示:存在pytest-random-order
将自动随机化测试,无需更改配置或命令行选项。
正如前面所解释的,这允许检测耦合测试 - 一个测试的状态影响另一个测试的状态。当安装了pytest-random-order
时,它将打印用于该会话的随机种子,例如:
pytest tests [...] Using --random-order-bucket=module Using --random-order-seed=573663
因此,如果给定的特定顺序失败,您可以通过添加确切的种子来重现它,例如:
pytest --random-order-seed=573663 [...] Using --random-order-bucket=module Using --random-order-seed=573663
只有在使用完全相同的测试列表(或根本没有列表)时,它才会重现确切的顺序。一旦开始手动缩小列表,就不能再依赖种子,而必须按照它们失败的确切顺序手动列出它们,并告诉 pytest 不要随机化它们,而是使用--random-order-bucket=none
,例如:
pytest --random-order-bucket=none tests/test_a.py tests/test_c.py tests/test_b.py
要禁用所有测试的洗牌:
pytest --random-order-bucket=none
默认情况下,隐含--random-order-bucket=module
,这将在模块级别对文件进行洗牌。它还可以在class
、package
、global
和none
级别进行洗牌。有关完整详情,请参阅其文档。
另一个随机化的替代方案是:pytest-randomly
。这个模块具有非常相似的功能/接口,但它没有pytest-random-order
中可用的桶模式。一旦安装,它也会强制自身。
外观和感觉变化
pytest-sugar
pytest-sugar 是一个插件,可以改善外观和感觉,添加进度条,并立即显示失败的测试和断言。安装后会自动激活。
pip install pytest-sugar
要在没有它的情况下运行测试,请运行:
pytest -p no:sugar
或者卸载它。
报告每个子测试的名称及其进度
通过pytest
运行单个或一组测试(在pip install pytest-pspec
之后):
pytest --pspec tests/test_optimization.py
立即显示失败的测试
pytest-instafail 立即显示失败和错误,而不是等到测试会话结束。
pip install pytest-instafail
pytest --instafail
要 GPU 还是不要 GPU
在启用 GPU 的设置中,要在仅 CPU 模式下测试,请添加CUDA_VISIBLE_DEVICES=""
:
CUDA_VISIBLE_DEVICES="" pytest tests/utils/test_logging.py
或者如果您有多个 GPU,可以指定pytest
要使用的 GPU。例如,如果您有 GPU 0
和 1
,则可以仅使用第二个 GPU 运行:
CUDA_VISIBLE_DEVICES="1" pytest tests/utils/test_logging.py
这在您想要在不同的 GPU 上运行不同任务时非常方便。
一些测试必须在仅 CPU 上运行,其他测试可以在 CPU 或 GPU 或 TPU 上运行,另一些测试可以在多个 GPU 上运行。以下跳过装饰器用于设置测试的 CPU/GPU/TPU 要求:
require_torch
- 此测试仅在 torch 下运行require_torch_gpu
- 与require_torch
相同,至少需要 1 个 GPUrequire_torch_multi_gpu
- 与require_torch
相同,至少需要 2 个 GPUrequire_torch_non_multi_gpu
- 与require_torch
相同,需要 0 个或 1 个 GPUrequire_torch_up_to_2_gpus
- 与require_torch
相同,需要 0 个或 1 个或 2 个 GPUrequire_torch_tpu
- 与require_torch
相同,至少需要 1 个 TPU
让我们在下表中描述 GPU 要求:
n 个 GPU | 装饰器 | --------±------------------------------- | >= 0 |
@require_torch |
>= 1 |
@require_torch_gpu |
>= 2 |
@require_torch_multi_gpu |
< 2 |
@require_torch_non_multi_gpu |
< 3 |
@require_torch_up_to_2_gpus |
例如,这是一个必须在有 2 个或更多个 GPU 可用且已安装 pytorch 时运行的测试:
@require_torch_multi_gpu def test_example_with_multi_gpu():
如果一个测试需要tensorflow
,请使用require_tf
装饰器。例如:
@require_tf def test_tf_thing_with_tensorflow():
这些装饰器可以叠加。例如,如果一个测试很慢并且在 pytorch 下至少需要一个 GPU,这是如何设置的:
@require_torch_gpu @slow def test_example_slow_on_gpu():
一些装饰器如@parametrized
会重写测试名称,因此@require_*
跳过装饰器必须在最后列出才能正常工作。以下是正确使用的示例:
@parameterized.expand(...) @require_torch_multi_gpu def test_integration_foo():
这个顺序问题在@pytest.mark.parametrize
中不存在,您可以将其放在最前面或最后面,它仍然有效。但它只适用于非单元测试。
在测试中:
- 有多少个 GPU 可用:
from transformers.testing_utils import get_gpu_count n_gpu = get_gpu_count() # works with torch and tf
使用特定的 PyTorch 后端或设备进行测试
要在特定的 torch 设备上运行测试套件,请添加TRANSFORMERS_TEST_DEVICE="$device"
,其中$device
是目标后端。例如,要仅在 CPU 上测试:
TRANSFORMERS_TEST_DEVICE="cpu" pytest tests/utils/test_logging.py
此变量对于测试自定义或不太常见的 PyTorch 后端(如mps
)很有用。它还可以用于通过定位特定 GPU 或在仅 CPU 模式下进行测试来实现与CUDA_VISIBLE_DEVICES
相同的效果。
在第一次导入torch
后,某些设备将需要额外的导入。这可以使用环境变量TRANSFORMERS_TEST_BACKEND
指定:
TRANSFORMERS_TEST_BACKEND="torch_npu" pytest tests/utils/test_logging.py
替代后端可能还需要替换特定于设备的函数。例如,torch.cuda.manual_seed
可能需要替换为特定于设备的种子设置器,如torch.npu.manual_seed
,以正确设置设备上的随机种子。在运行测试套件时指定新的后端和后端特定设备函数时,创建一个 Python 设备规范文件,格式如下:
import torch import torch_npu # !! Further additional imports can be added here !! # Specify the device name (eg. 'cuda', 'cpu', 'npu') DEVICE_NAME = 'npu' # Specify device-specific backends to dispatch to. # If not specified, will fallback to 'default' in 'testing_utils.py` MANUAL_SEED_FN = torch.npu.manual_seed EMPTY_CACHE_FN = torch.npu.empty_cache DEVICE_COUNT_FN = torch.npu.device_count
此格式还允许指定所需的任何其他导入。要使用此文件替换测试套件中的等效方法,请将环境变量TRANSFORMERS_TEST_DEVICE_SPEC
设置为规范文件的路径。
目前,只支持MANUAL_SEED_FN
、EMPTY_CACHE_FN
和DEVICE_COUNT_FN
用于特定设备的分发。
分布式训练
pytest
不能直接处理分布式训练。如果尝试这样做-子进程不会做正确的事情,最终会认为它们是pytest
并开始循环运行测试套件。但是,如果生成一个正常进程,然后生成多个工作进程并管理 IO 管道,则可以正常工作。
以下是一些使用它的测试:
要直接跳转到执行点,请在这些测试中搜索execute_subprocess_async
调用。
您至少需要 2 个 GPU 才能看到这些测试的运行情况:
CUDA_VISIBLE_DEVICES=0,1 RUN_SLOW=1 pytest -sv tests/test_trainer_distributed.py
输出捕获
在测试执行期间,发送到stdout
和stderr
的任何输出都将被捕获。如果测试或设置方法失败,则通常会显示其相应的捕获输出以及失败的回溯。
要禁用输出捕获并正常获取stdout
和stderr
,请使用-s
或--capture=no
:
pytest -s tests/utils/test_logging.py
将测试结果发送到 JUnit 格式的输出:
py.test tests --junitxml=result.xml
颜色控制
要没有颜色(例如,白色背景上的黄色不可读):
pytest --color=no tests/utils/test_logging.py
将测试报告发送到在线粘贴服务
为每个测试失败创建一个 URL:
pytest --pastebin=failed tests/utils/test_logging.py
这将向远程粘贴服务提交测试运行信息,并为每个失败提供一个 URL。您可以像往常一样选择测试,或者例如添加-x
,如果您只想发送一个特定的失败。
为整个测试会话日志创建一个 URL:
pytest --pastebin=all tests/utils/test_logging.py
Transformers 4.37 中文文档(十一)(3)https://developer.aliyun.com/article/1564973